首页 > 解决方案 > 使用内连接删除需要 40 多秒才能删除 500 行

问题描述

我有这个要求:

delete L 
from L
inner join M on L.id = M.ref_id 
             or L.id = M.news_id 

完成删除 588 行需要 39 到 50 秒。

如果在我的查询中替换delete L from L为,则选择非常快 0,015 秒select * from L

这是我在 xml 中的跟踪

这是我的解释计划文件 .SQLPlan

希望你能帮助我在这里缺少什么,这里有什么问题?

标签: sqlsql-servertsqljoininner-join

解决方案


从大型聚簇表中删除行通常很慢。

评论中讨论的著名“BETWEEN”是聚集索引的一个分区,它从您的连接中获取最小值和最大值。所以建议批量删除。

我想可能没有什么一般性建议,但它总是取决于不同的因素,例如数据量、硬件、内存、日志文件大小等。 - 批量删除行。最佳批量大小取决于环境,但通常在 10K 到 100K 左右。- 按聚集索引的顺序删除 - 如果可能,将您的恢复模式设置为 BULK/SIMPLE 以减少日志记录。- 如果可能的话,从子表中删除约束,如外键约束。- 如果可能,禁用非聚集索引 - 根据您要删除的数据量,最好将数据导出到新表,然后删除旧表或为将来保留不同的名称参考。如您所见,主要取决于情况和环境。

这是最好的答案,“也许你需要调整系统,而不是查询”

但是从删除语句中,我更愿意看到大部分成本来自删除本身。了解,聚集索引是将数据存储在具有聚集索引的表中的位置。删除时,您将从集群中删除。这并不是说您可能无法进一步调整它,但您会看到非常正常,甚至是理想的行为。如果没有确切地看到你在做什么,很难提出建议,但可能是你做得很好。在这种情况下,也许您需要调整系统,而不是查询。获得更快的磁盘。确保您没有承受内存压力。检查您的等待统计信息,以了解大部分工作在服务器上完成的位置,并从那里进行调整。

如果你不能做任何这些事情,使用循环逐行删除可能会更快......

来源:https ://ask.sqlservercentral.com/questions/90223/how-to-reduce-the-cost-of-clustered-index-delete.html


推荐阅读