1

一般来说,我对 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

显示 FirstAttempt 批次的 32% 和 SecondAttempt 的 68%

PersonWord表包含大约 4100 万条记录...该Person表包含大约 170,000条记录

任何想法/建议都将受到欢迎。感谢您抽出宝贵的时间,我知道新手问题是多么令人沮丧(用于在 Yahoo 上做数学帮助)。

编辑::

在拥有大约 130 万条记录的 PersonWord 和拥有大约 3000 条记录的 PersonWord 上运行那些......具有合并的版本大约需要 1.3 秒才能执行。带有 while 循环的版本用时 6 分钟,只完成了约 15% 的工作。

对于这种事情,基于集合而不是 RBAR!

4

1 回答 1

3

永远不要将表变量用于该数量的记录。它们适用于小型数据集。请改用临时表并将其编入索引。此外,我个人会寻找一种方法来限制您正在更新的记录数量。我不确定您为什么要使用合并,因为这是一个简单的更新。下面的代码应该可以工作。

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 *价值))

顺便说一句,对于任何数学计算来说,浮动都是一种不好的做法,因为它不准确,所以会引入舍入误差。

于 2013-05-14T21:30:02.147 回答