简单的 DELETE,但复杂的执行计划

Cra*_* HB 9 performance sql-server-2008 execution-plan query-performance

当我运行此删除时:

DELETE FROM ETLHeaders WHERE ETLHeaderID < 32465870
Run Code Online (Sandbox Code Playgroud)

...它删除了 39,157 行。它应该很简单,因为它是在 ETLHeaderID 上删除的,它是聚集索引和主键。但是(根据执行计划)它似乎达到了 361,190 行并使用了其他索引。该表确实有一个具有 XML 数据类型的字段(以防影响此 DELETE)。

任何想法为什么以及如何加速此 DELETE?

此处的执行计划: http ://sharetext.org/qwDY 此处的表架构:http : //sharetext.org/Vl9j

谢谢

Pau*_*ite 12

该计划的顶层涉及从基表(聚集索引)中删除行,并维护四个非聚集索引。在处理聚集索引删除的同时,这些索引中的两个被逐行维护。这些是下面以绿色突出显示的“+2 非聚集索引”。

对于其他两个非聚集索引,优化器决定最好将这些索引的键保存到 tempdb 工作表(Eager Spool),然后播放两次假脱机,按索引键排序以促进顺序访问模式。

定期索引维护

最终的操作序列与维护主xml索引和二级索引有关,这些索引未包含在您的 DDL 脚本中:

XML 索引维护

对此没有太多可做的。非聚集索引和xml索引必须与基表中的数据保持同步。在表上创建额外索引时,维护此类索引的成本是权衡的一部分。

也就是说,xml索引尤其成问题。优化器很难准确评估在这种情况下有多少行符合条件。事实上,它极大地高估了xml索引,导致为该查询分配了近 12GB 的内存(尽管在运行时仅使用了 28MB):

估计行数

您可以考虑小批量删除,希望能减少过多的内存授予的影响。

您还可以测试计划的性能,而无需使用OPTION (QUERYTRACEON 8795). 这是一个未记录的跟踪标志,因此您应该只在开发或测试系统上尝试它,而不要在生产中尝试。如果生成的计划要快得多,您可以捕获计划 XML 并使用它为生产查询创建计划指南