Sql SELECT中的多个乘法是否可以分解为只对所有行执行一次?

Sql SELECT中的多个乘法是否可以分解为只对所有行执行一次?,sql,optimization,query-optimization,Sql,Optimization,Query Optimization,假设我有以下SQL查询,涉及“AS…”阶段的浮点操作 其中TableName有5.000.000行,而A、B、C和D是A中的行,它们是不同的行。2个问题: 1.A*B*C会实际执行100次吗? 2-是否有方法将a*B*C运算分解为一行100列只执行一次的2次循环乘法 此外,我们可以认为“B”将是一个复函数调用(SQRT(ARTCTAN(…(x))),因此合法性只想在每一个行< /强>下执行。 < P>我假定它将预先计算它能(SQL Server),然后将它应用到列()。 我很确定,如果你把相乘的

假设我有以下SQL查询,涉及“AS…”阶段的浮点操作

其中TableName有5.000.000行,而A、B、C和D是A中的行,它们是不同的行。2个问题:

1.A*B*C会实际执行100次吗? 2-是否有方法将a*B*C运算分解为一行100列只执行一次的2次循环乘法


此外,我们可以认为“B”将是一个复函数调用(SQRT(ARTCTAN(…(x))),因此合法性只想在每一个<强>行< /强>下执行。

< P>我假定它将预先计算它能(SQL Server),然后将它应用到列(

)。 我很确定,如果你把相乘的数字放在一行,交叉连接选择,就可以了。比如:

select D1 * res
from tableName
cross join (select A * B * C as res) as multiplied
CREATE TABLE TableName
 (
   A  float  not null
  ,B  float  not null
  ,C  float  not null
  ,AxBxC  AS  A * B * C
 )
编辑

如果数据是列,而不是标量值,则可能:

select t1.D1 * myAlias.res, t1.D2 * myAlias.res, t1.D3 * myAlias.res
from tableName t1
inner join 
    (
    select t2.keyCol, t2.A * t2.B * t2.C as res
    from tableName t2
    ) myAlias 
on t1.keyCol = myAlias.keyCol

一种方法可能是在表上创建一个计算列。在SQL Server中,这类似于:

select D1 * res
from tableName
cross join (select A * B * C as res) as multiplied
CREATE TABLE TableName
 (
   A  float  not null
  ,B  float  not null
  ,C  float  not null
  ,AxBxC  AS  A * B * C
 )
该列(好的,应该的,这取决于RDBMS是如何实现的)每读取一行计算一次,并在以后每次使用。作为计算列,该公式为表存储一次,因此不会显著增加存储空间


更新问题的更新:

您现在正在执行一个涉及5000000行的三向表连接(一个外部连接,不少于5000000行)。这将很容易达到10s,也许100s,兆字节的磁盘I/O(除非从以前的读取中缓存数据),并需要合并、循环、散列连接等来连接所有数据。到所有这些完成时,仅执行算术运算所需的CPU量相比之下将微不足道。CPU擅长数学

要测试这一点:

  • 构建并运行“完整”查询,如您的问题所示
  • 构建并运行只返回a*B*C计算的查询
  • 使用“calc once”查询,并将其用作连接到“base”查询中的子查询或临时表
最后一种是我能想到的强制SQL每行只执行一次计算的唯一方法。但是,这会增加一个连接(跨越500万行),从我所见过或读到的所有内容来看,这是性能最受影响的地方


(如果你做这个测试,我会非常感兴趣地看到结果!)

从表中获取行比乘以这些数字要困难得多。有多少是“远”?:)如果“*”是一个复杂的函数调用(SQRT等…)假设a、B、C或d来自表a,是的,它需要对每一行进行反复计算。现在,如果ABC=E是静态的,那么你为什么不直接用硬件值E来代替呢(如果你真的想简化事情的话)@Limey:谢谢:我刚刚编辑了我有缺陷的问题。事实上,每行的值都会发生变化,我将10米的出现次数替换为100。那么您每次将选择5米的行?没有WHERE条款吗?(我这样问是因为A1-A100列上的哪一列不能使用任何索引!)有价值的答案。现在,如果select的A、B和C都来自不同的输入表(JOINED)@SkippyFastol,那么您可能需要使用一个(物化的)视图,我看不出这是如何解决问题的。A、 B和C来自一张桌子;它们不是常数。根据最初的帖子,我的理解是它们不是来自表中。因此,我的评论是,我希望SQL Server足够聪明,能够预先计算任何标量乘法,然后将该结果应用于列中的数据。如果ID字段上有聚集索引,则可以使用别名相当有效地将表连接到表本身,然后仍然使用大致相同的上述原则。