我有两个表 - SourceTable和DestTable - Source包含RowNum和Col的列。我想在Col上加入两个表,然后更新top' n' DestTable的行,其中' n'是SourceTable中RowNum的值。我可以通过交叉申请来做到这一点,但需要几个小时。我正在寻找另一种编写此查询的方法。
My Cross Apply解决方案是 -
UPDATE t
SET dest = source
FROM #sourcetable s
CROSS apply (SELECT TOP(s.rownum) *
FROM #desttable d
WHERE d.col = s.col) t
以下是样本数据 -
SourceTable -
Col, Source, RowNum
11 , 111 , 2
12 , 222 , 1
DestTable(更新前) -
Id, Col, Dest
1 , 11 , 0
2 , 11 , 0
3 , 11 , 0
4 , 12 , 0
5 , 12 , 0
DestTable(更新后) -
Id, Col, Dest
1, 11, 111
2, 11, 111
3, 11, 0
4, 12, 222
5, 12, 0
但这表现得非常差(即使在正确索引的表上,当行数为几百万且列接近400时需要数小时)。
是否有更有效的方法来编写此查询?
更新 - 实际表结构如下 -
DestTable (包含大约1百万条记录,每个列都已填充) - 38个日期时间,66个浮点数,31个int,210个varchar(50)字段
可输入(它是在相关sql运行之前创建的临时表,包含大约100k条记录并且每列都已填充) - 总共16个字段(4个int,2个datetime,1个float ,rest varchar(50))
索引 - 我无法创建包含所有必填字段的覆盖索引,因为它们因查询而异。我尝试在各种字段组合上创建索引,发现更新运行速度明显更快,没有任何索引。
当前测试结果(行数在DestTable中) -
1000行(没有任何索引) - 05:00分钟
10000行(没有任何索引) - 17:38分钟
100000行(没有任何索引) - 3小时7分钟
100000(4个字段上有任何索引) - 超过7个小时我不得不停止它
答案 0 :(得分:2)
您可以尝试使用简单的JOIN
代替相关的子查询:
WITH cte AS
(
SELECT d.id, d.col, d.dest, s.source
FROM (SELECT *,
rn = ROW_NUMBER() OVER(PARTITION BY col ORDER BY id) FROM #desttable) d
JOIN #sourcetable s
ON d.col = s.col
AND d.rn <= s.rownum
)
UPDATE cte
SET dest = source;
SELECT *
FROM #desttable;
的 LiveDemo
强>
您应该发布您的真实数据样本,数据结构和查询计划。否则我们只能猜测如何改进它。