【发布时间】:2016-07-13 18:12:25
【问题描述】:
我有两个表 - SourceTable 和 DestTable - Source 包含列 RowNum 和 Col。我想加入 Col 上的两个表,然后更新 DestTable 的前“n”行,其中“n”是 SourceTable 中 RowNum 的值。我可以通过交叉应用来做到这一点,但这需要几个小时。我正在寻找另一种编写此查询的方式。
我的 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
以下是样本数据-
源表-
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(包含大约 100 万条记录,每列都已填充)- 38 个日期时间、66 个浮点数、31 个整数、210 个 varchar(50) 字段
Sourceable(它是在相关 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 小时我不得不停止它
【问题讨论】:
-
我可以理解数百万行会使这变慢,但您需要解释多列如何影响这一点。此外,性能问题应包括
EXPLAIN ANALYZE以及有关表大小、索引、当前时间性能、期望时间等的一些信息。Slow是一个相对术语,我们需要一个实际值来比较。 -
谢谢,我添加了有关表结构和当前性能的信息。 100 万行所需的时间少于 20 分钟。我不确定解释分析是什么。它是一个标签还是应该添加到问题中的东西?
-
将大更新拆分成小更新几乎总是明智之举,因为……嗯,大事务往往很慢。您是否尝试过使用光标,一次一个列?
-
这是EXPLAIN PLAN ...顺便说一句,如果 1000 条记录是 5 分钟是非常合理的,说 100k 需要 3 小时。看起来时间增加与行数成线性关系。因此,如果您改进 1000 行的时间,其他的也会改进。
-
知道了。我只更新一栏。让我问你一些别的问题 - 生成多个线程以同时更新不同的行是一个好主意吗(一个线程用于前一千行,另一个线程用于接下来的一千行等等)?我不知道数据库内部是如何工作的,不确定这是否会有所帮助或使事情变得更糟。
标签: sql sql-server tsql