一般来说,我对SQL和数据库都是很陌生的。我正在使用SQL Server 2008 Mgmt Studio。
我读到过使用基于集合的操作比使用RBAR更好(这是今天才学到的!)
稍后,我将向您展示两个等价的(我认为)查询,并尝试查看哪一个更有效。
第一次尝试:
DECLARE @persID int
DECLARE @mag float
DECLARE @temp TABLE (pID int PRIMARY KEY)
INSERT INTO @temp
SELECT persID FROM Person
WHILE (SELECT COUNT(pID) FROM @temp) > 0
BEGIN
SELECT TOP 1 @persID = pID FROM @temp
SELECT @mag = SQRT(SUM(value*value)) FROM PersonWord
WHERE PersonWord.persID = @persID
UPDATE Person
SET magnitude = @mag
WHERE persID = @persID
DELETE @temp WHERE pID = @persID
END第二次尝试:
DECLARE @temp TABLE (pID int PRIMARY KEY, mag float)
INSERT INTO @temp
SELECT persID, SQRT(SUM(value*value)) FROM PersonWord
GROUP BY persID
MERGE INTO Person AS p
USING @temp AS t
ON p.persID = t.pID
WHEN MATCHED
THEN UPDATE
SET magnitude = t.mag这些将保存为存储过程和运行时的估计执行计划:
exec FirstAttempt
exec SecondAttempt显示32%的批次用于FirstAttempt,68%用于SecondAttempt
PersonWord表包含约4100万records...the Person表包含约170,000
任何想法/建议都是非常受欢迎的。感谢你抽出时间,我知道新手问题有多令人沮丧(在雅虎上做数学帮助)。
编辑::
在PersonWord上运行那些拥有大约130万条记录和大约3000条记录的人...具有merge的版本花了大约1.3秒来执行。带有while循环的版本只有6分钟,并且只完成了大约15%的作业。
对于这类事情,使用Set-based而不是RBAR!
发布于 2013-05-15 05:30:02
永远不要使用表变量来表示该数量的记录。它们是针对小数据集的。请改用临时表,并为其编制索引。此外,我个人会寻找一种方法来限制您正在更新的记录的数量。我不知道你为什么要使用合并,因为这只是一个简单的更新。下面的代码应该可以工作。
Update P
set SET magnitude = t.mag
from Person AS p
join #temp AS t
ON p.persID = t.pID
WHERE magnitude <> t.mag根据您执行此操作的频率,我将尝试存储此计算,以便每条记录只需要执行一次计算(并使用rtigger在值发生变化时保持更新):SQRT(SUM(value*value))
顺便说一句,在任何数学计算中使用浮点数都是一种糟糕的做法,因为它并不精确,因此会引入舍入误差。
https://stackoverflow.com/questions/16552671
复制相似问题