sql - SQL-SERVER 为什么我的级联删除卡住了
问题描述
我有一个大约有 100 个表的数据库。Client
几乎所有其他表(直接或间接)都引用了一个表。
我正在尝试Client
通过执行此查询来删除一个的所有数据:
DELETE FROM Client
WHERE Id = SomeNumber
此查询应CASCADE
删除所有表中的所有行
直接或间接地与此Id
有关Client
问题是查询卡住了,我不明白为什么。
这是查询计划
我通过这个脚本检查了锁
select * from sysprocesses where blocked > 0
但没有结果。也没有收到任何错误。而且我的数据库中没有任何触发器。
我确实看到某个表中的几百行已被删除,但是
几秒钟后,查询卡住了。
解决方案
您可以在计划中非常清楚地看到,一些依赖表在外键中没有索引。
当级联发生时,计划首先将所有行转储到内存表中。Table Spool
您可以在计划的左上角看到这一点,以Clustered Delete
.
然后它读回这些行,并将它们连接到依赖表。这些表必须有一个以外键为前导键的索引,否则您将获得全表扫描。
在您的大量表中发生了这种情况,在某些情况下,通过两次扫描和哈希连接进行双重级联。
创建索引时,不要只创建单列索引。与其他列和INCLUDE
列创建合理的索引,只需确保外键是前导列。
我必须说,有这么多外键,你总是会遇到一些问题,因此你可能想要关闭CASCADE
。
推荐阅读
- java - 持有 RecyclerView 的片段未显示在 MainActivity 中
- python - 如何在 matplotlib 中为散点图和折线图设置动画
- elasticsearch - Elasticsearch Ngrams:自动完成的意外行为
- ruby - 无 DateTime 的 Ruby Benign vale
- sphinx - 狮身人面像不工作 - 状态活动(退出)
- reactjs - 无法读取未定义的属性 'then' | 当我尝试使用 babel-dynamic-import 导入组件时
- java - 为什么我的 java 方法在 return 语句之后执行行?
- mysql - 将具有重复值的行转换为列 - MySQL
- apache-spark-sql - Databricks getArgument 值不能在 Spark SQL IN 子句中使用
- android - 如何在 android 中使用 Cpp 库中的 SQLite?