我在SQL Server 2012(网络版)中有一个非常大的表(150米+行),它没有聚簇索引和一个非聚集索引。
当我运行此删除语句时:
DELETE TOP(500000)
FROM pick
WHERE tournament_id < 157
(列名在非聚集索引中),SQL Server生成的执行计划如下所示:
排序步骤看起来有问题 - 它占用了45%的成本,并且它正在引发一条警告说“操作员在执行期间使用tempdb溢出数据”。该查询需要几分钟才能运行,我觉得它应该更快。
两个问题:
如果可能有帮助,我绝对可以重新访问此表上的索引策略。
希望这一切都有意义 - 提前感谢任何提示。
答案 0 :(得分:6)
我同意这里似乎没有充分的理由。
我不认为万圣节保护需要它,因为它没有出现在计划的= 157
版本中。
此外,排序操作按Key Asc, Bmk ASC
的顺序排序(可能是按照索引顺序按顺序排序),但这是正向索引在同一索引上搜索的顺序,无论如何都要返回行。 / p>
删除它的一种方法是混淆TOP
以获得狭窄(每行)而不是宽(每个索引)计划。
DECLARE @N INT = 500000
DELETE TOP(@N)
FROM pick
WHERE tournament_id < 157
OPTION (OPTIMIZE FOR (@N=1))
您需要进行测试,看看这是否真的有所改善。
答案 1 :(得分:3)
我会尝试更小的块和更具选择性的WHERE子句,以及强制SQL Server按照您指定的顺序选择TOP行的方法:
;WITH x AS
(
SELECT TOP (10000) tournament_id
FROM dbo.pick
WHERE tournament_id < 157 -- AND some other where clause perhaps?
ORDER BY tournament_id -- , AND some other ordering column
)
DELETE x;
更具选择性也可能意味着删除tournament_id&lt; 20,然后是tournament_id&lt; 40等,而不是从1-157中挑选500000个随机行。通常情况下,对整个系统(阻止影响,锁定升级等以及对日志的影响)执行一系列小事务而不是一个大事务更好。我在这里写了博客:http://www.sqlperformance.com/2013/03/io-subsystem/chunk-deletes
在这些情况下可能仍然存在这种情况(特别是如果它适用于Hallowe'en保护或与RID有关),但在较小的范围内它可能远没有问题(请不要只是基于在那个估计的成本%数,因为这些数字通常是垃圾)。所以首先我要考虑添加聚簇索引。没有更多的要求我没有给你一个明确的建议,但它可以像仅在tournament_id上的聚集索引一样简单(取决于你每个id有多少潜在的行)或添加你可能使用的IDENTITY列帮助确定将来要删除的行。
答案 2 :(得分:2)
我是以下步骤:
根据我的经验,这应该会有几秒钟。
此外,如果可能,我会对您的表格进行更详细的查询。
版本1(日期格式为dd / mm / yyyy):
;WITH To_Delete
(
SELECT tournament_id
FROM dbo.pick
WHERE tournmanet_id < 157
AND date like '01/%/2013' -- if available, Need to be customized
AND date like '03/%/2013' -- if available, Need to be customized
)
DELETE X;
Verion 2(具有month
功能,无论您的日期具有哪种格式):
;WITH To_Delete
(
SELECT tournament_id
FROM dbo.pick
WHERE tournmanet_id < 157
AND month(date) = 1
AND month(date) < 3
)
DELETE X;