可以将SELECT中的多个乘法分解为仅对所有行执行一次吗?

时间:2012-06-27 12:52:40

标签: sql optimization query-optimization

假设我有以下SQL查询,涉及“AS ...”阶段的浮点运算。

SELECT

T1.A * T2.B *  T1.D1 * T3.C AS A1
T1.A * T2.B *  T1.D2 * T3.C AS A2
(...)
T1.A * T2.B * T1.D100 * T3.C  AS A100

FROM TableName1 as T1
INNER JOIN TableName2 AS T2
LEFT JOIN  TableName3 AS T3

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

1 - A * B * C 实际执行 100次吗? 2 - 有没有一种方法可以将2次重复乘法的 A * B * C 运算分解为一行的100列只执行一次?

另外,我们可以认为“B”例如是一个复杂的函数调用(SQRT(ARTCTAN(...(x))),因此每个行只需要执行一次的合法性

2 个答案:

答案 0 :(得分:3)

我认为它会预先计算它可以(SQL Server),然后将其应用于列。

我很确定你是否将乘法数字放在单行,交叉连接选择中,这样就可以了。类似的东西:

select D1 * res
from tableName
cross join (select A * B * C as res) as multiplied

修改

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

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

答案 1 :(得分:0)

一种方法可能是在表上创建计算列。在SQL Server中,它看起来像:

CREATE TABLE TableName
 (
   A  float  not null
  ,B  float  not null
  ,C  float  not null
  ,AxBxC  AS  A * B * C
 )

列将(确定,应该,它取决于RDBMS的实现方式)每行读取一次并在此后每次使用。作为caluclated列,公式存储一次用于表,因此无法测量增加存储空间。


更新更新的问题:

您现在正在执行涉及5,000,000行的三向表连接(外部连接,不能少)。这将很容易达到10s,也许是100s,兆字节的磁盘I / O(除非数据是从先前的读取缓存的),并且需要合并,循环,散列连接以及所有数据的链接。在完成所有这些工作之后,相比之下,执行光学算法所需的CPU数量将是微不足道的。数学上的CPU

测试一下:

  • 构建并运行“完整”查询,如您的问题
  • 构建并运行一个返回 A * B * C计算的查询。
  • 获取“calc once”查询,并将其用作加入“基本”查询的子查询或临时表。

这是我能想到的唯一一种强制SQL每行执行一次计算的方法。然而,这引发了额外的连接(跨越500万行),以及我所见过或读过的所有内容,这是您的性能受到最大影响的地方。

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