我在SQL Server 2012(网络版)中有一个非常大的表(150米+行),它没有聚簇索引和一个非聚集索引.
当我运行这个删除语句时:
DELETE TOP(500000)
FROM pick
WHERE tournament_id < 157
Run Code Online (Sandbox Code Playgroud)
(列名在非聚集索引中),SQL Server生成的执行计划如下所示:

排序步骤看起来有问题 - 它占用了45%的成本,并且它引发了一个警告,说"操作员在执行期间使用tempdb溢出数据".查询需要几分钟才能运行,我觉得它应该更快.
两个问题:
如果这可能会有所帮助,我绝对可以重新审视此表上的索引策略.
希望这一切都有意义 - 提前感谢任何提示.
我同意这里似乎没有充分的理由.
我不认为万圣节保护需要它,因为它没有出现在= 157计划的版本中.
此外,排序操作按顺序排序Key Asc, Bmk ASC(可能是按索引顺序按顺序排序),但这是正向索引在同一索引上搜索的顺序,无论如何都要返回行.
删除它的一种方法是混淆TOP以获得狭窄(每行)而不是宽(每个索引)计划.
DECLARE @N INT = 500000
DELETE TOP(@N)
FROM pick
WHERE tournament_id < 157
OPTION (OPTIMIZE FOR (@N=1))
Run Code Online (Sandbox Code Playgroud)

您需要进行测试,看看这是否真的改善了.
我会尝试更小的块和更具选择性的 WHERE 子句,以及强制 SQL Server 按照您指定的顺序选择顶部行的方法:
;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;
Run Code Online (Sandbox Code Playgroud)
更具选择性还可能意味着删除tournament_id < 20,然后删除tournament_id < 40,等等,而不是从1-157中挑选500000个随机行。通常,执行一系列小事务而不是一个大事务对您的系统整体来说(无论是在阻塞影响、锁升级等方面,还是对日志的影响方面)更好。我在这里写了一篇博客:http://www.sqlperformance.com/2013/03/io-subsystem/chunk-deletes
在这些情况下,排序可能仍然存在(特别是如果它是为了万圣节保护或与 RID 有关的事情),但在较小的范围内,问题可能要小得多(请不要仅仅基于估计的值)成本%数字,因为这些数字通常是垃圾)。所以首先我真的会考虑添加聚集索引。如果没有更多要求,我没有给您明确的建议,但它可以像仅在tournament_id上的聚集索引一样简单(取决于每个id有多少潜在行)或添加一个您可能会使用的IDENTITY列帮助确定将来要删除的行。