假设我有以下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 - 有没有办法分解 A * B * C 运算,以便对一行的 100 列仅执行一次的 2 次循环乘法?
此外,我们可以认为"B"将是一个复杂的函数调用(SQRT(ARTCTAN(...(x))),因此每行只想执行一次的合法性。
我认为它会预先计算它可以计算的内容(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
一种方法可能是在表上创建计算列。在SQL Server中,这看起来像这样:
CREATE TABLE TableName
(
A float not null
,B float not null
,C float not null
,AxBxC AS A * B * C
)
该列将(好吧,应该,这取决于RDBMS是如何实现的)每读取一行计算一次,然后每次使用。作为校准列,公式为表存储一次,因此不会显著增加存储空间。
更新问题:
您现在正在执行涉及 5,000,000 行的三向表联接(一个外联接,不少)。这将很容易达到 10 兆字节,也许是 100 兆字节的磁盘 I/O(除非数据是从先前的读取中缓存的),并且需要合并、循环、哈希连接等来链接所有数据。到完成所有这些操作时,相比之下,执行算术所需的CPU量将是微不足道的。CPU擅长数学。
要对此进行测试,请执行以下操作:
- 构建并运行"完整"查询,如您的问题中所述
- 生成并运行仅返回 A * B* C 计算的查询。
- 采用"calc once"查询,并将其用作联接到"base"查询的子查询或临时表。
最后一种方法是我能想到的强制SQL每行只执行一次计算的唯一方法。但是,这会带来额外的联接(跨越 500 万行),从我所见过或读到的所有内容来看,这就是您的性能受到最大影响的地方。
(如果你做这个测试,我会非常感兴趣地看到结果!