我正在寻找任何建议来优化 SAS 程序中的以下 PROC SQL 语句。涉及的两个表每个包含大约 500 万条记录,运行时间约为 46 小时。
该语句希望更新“旧”表的"new"版本。如果“旧”表的“PK_ID”列没有“3RD_ID”和“CODE”的值,则注意一列,但在"new"表中,对于“PK_ID”,它现在列出“3RD_ID”和“CODE”的值。
感谢您的任何建议......(代码的格式确实如下!由于某些原因,我的空格没有显示缩进......)
PROC SQL _METHOD;
UPDATE NEW_TABLE AS N
SET NEW_2ND_ID=(SELECT 2ND_ID FROM OLD_TABLE AS O
WHERE N.PK_ID=0.PK_ID
AND N.2ND_ID<>O.2ND_ID
AND O.3RD_ID IS NULL
AND O.CODE IS NULL
AND N.3RD_ID IS NOT NULL
AND N.CODE IS NOT NULL
AND N.2ND_ID IS NOT NULL)
WHERE N.3RD_ID IS NOT NULL
AND N.PK_ID IS NOT NULL
AND N.CODE IS NOT NULL
AND N.2ND_ID IS NOT NULL;
QUIT;
最佳答案
我不熟悉您使用的 SQL 变体。但是,无论您是否获得更好的性能,都应该使用 ANSI 连接语法。这是它在 T-SQL 中的样子,请为您的系统修改它:
UPDATE N
SET N.2ND_ID = O.2ND_ID
FROM
NEW_TABLE AS N
INNER JOIN OLD_TABLE AS O ON N.PK_ID = O.PK_ID
WHERE
N.2ND_ID <> O.2ND_ID
AND N.3RD_ID IS NOT NULL
AND O.3RD_ID IS NULL
AND N.CODE IS NOT NULL
AND O.CODE IS NULL
请注意,我删除的额外条件不是必需的,例如
N.2ND_ID <> O.2ND_ID
已经保证这两列不为空。但是,在两个 500 万行的表上,您将获得糟糕的性能。这里有一些想法可以加快速度。我敢打赌,通过正确的策略组合,您可以将时间缩短到一个小时以内。
DECLARE
@ID int,
@Count int
SET @ID = 1
SET @Count = 1
WHILE @Count > 0 BEGIN
UPDATE N
SET N.2ND_ID = O.2ND_ID
FROM
NEW_TABLE AS N
INNER JOIN OLD_TABLE AS O ON N.PK_ID = O.PK_ID
WHERE
N.2ND_ID <> O.2ND_ID
AND N.3RD_ID IS NOT NULL
AND O.3RD_ID IS NULL
AND N.CODE IS NOT NULL
AND O.CODE IS NULL
AND N.PK_ID BETWEEN @ID AND @ID + 4999
SET @Count = @@RowCount
SET @ID = @ID + 5000
END
此示例假设您的 PK_ID 列密集,每次更新将真正达到 5000 行。如果不是这种情况,则切换到使用 TOP 5000 的方法,并将更新的 PK_ID 输出到表中,或者一步找到下一次更新的 @StartID 和 @EndID,然后执行它。
根据我的经验,好的批量大小往往在 1000 到 20000 行之间。在 MS-SQL 服务器中,甜蜜点似乎刚好低于强制从搜索切换到扫描的数字(因为最终,数据库引擎假设单次扫描比多次搜索便宜,尽管它通常是处理 500 万行表时出错)。
关于sql - SQL UPDATE 语句所需的优化建议。使用了大约 500 万个记录表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2155177/