我有一个相对较小的数据库,可能有几十万行,我们有一个存储过程,旨在清除“经销商”(应用程序聚合根)及其所有相关数据。该数据库位于 v12 Azure SQL 实例上,当它访问一个特定的表时,它会消耗该实例 100% 的 DTU/CPU,并且需要很长时间才能完成。
我认为问题在于该表有大量外键,可能大约 30 个。查看执行计划,您可以看到它正在执行大量Nested Loop
索引扫描以查找相关行。在尝试从该特定表中删除行之前,所有这些行都已被删除,因此这些循环实际上毫无意义。
我的问题是,禁用这些依赖表上的外键约束,删除,然后重新启用约束会更有效吗?这样做会不会产生一些负面影响,除了在技术上可能会在禁用约束时插入一些坏数据这一事实。还是有更好的方法来完成我想要完成的事情?
更新 这是一个 v12 Azure SQL 数据库,它不是 VM 中完整的 SQL Server 2012。我没有批量删除任何删除,有问题的语句是更大的 SPROC 的一部分。我通过撕开存储过程并分别运行它的零碎部分来识别这个特定的表删除。当它到达这张桌子时,实际上需要 15 分钟才能完成。它将影响数百行的顺序,具体取决于我们正在清除的特定“经销商”的状态。
在这种情况下我们不能进行软删除,因为通常我们会清除这个经销商以便可以替换它(软删除会导致重复并且需要大量代码来解决)。我调查了其他类型的阻塞和等待状态,没有发现其他似乎对此产生负面影响的东西。正如我提到的,这个数据库相对较小,主要用于非常简单的 CRUD 操作。
执行计划的 XML 版本可以在这里找到:https ://gist.github.com/CodingGorilla/6cf7a87df9257d5f93e0d545af9839c2