想象一个简单的表结构:
Table1 Table2
---------- ----------
ID<-------| ID
Name |-->Table1ID
Name
Table1
有几百万行(例如350万行)。我按主键发出删除:
DELETE FROM Table1 WHERE ID = 100;
Table2
中没有行引用Table1
ID = 100
,因此删除工作时不会违反任何外键约束。
您希望删除多长时间?大约几毫秒?几百毫秒?一秒钟还是更多?几秒钟?等等,假设机器没有陷入困境并随时处理请求。
现在,我有这种情况,这样的删除大约需要700毫秒。对我来说,这似乎太慢了。我很好奇,如果我离开基地,或者其他人都认为这太慢了,并建议帮助加快速度!
以下是实际执行计划:
(此处为XML执行计划:http://pastebin.com/q9hSMLi3)
聚集索引删除(81%)命中聚类PK,非聚类唯一索引和非聚类非唯一索引。
答案 0 :(得分:4)
问题是用于验证外键的聚簇索引扫描。
如果删除成功并且没有可能导致违规的匹配记录,则需要扫描所有table2
。这个表有1,117,190行,所以这是一个昂贵的操作,肯定可以从索引中受益。
执行计划中显示的10%数字只是基于某些建模假设的估计值。
整个计划的费用为0.0369164
,表2中的扫描费用为0.0036199
,其他所有费用都计入剩余的0.0332965
。但请注意,对于聚簇索引扫描运算符,估计的CPU成本为1.22907
,估计的IO成本为10.7142
(总计11.94327
而非0.0369164
)。
出现这种差异的原因是扫描位于反半连接操作符下,一旦找到匹配的行,扫描就会停止。估计的子树成本在建模假设下按比例缩小,即只有在扫描了一小部分表后才会发生这种情况。
如果没有FK违规并且删除成功,则需要扫描整个表,以便使用未缩放的向下数字提供更多信息。
如果使用代表实际发生的完整扫描的运算符的11.94327
成本重新设置百分比,则此扫描运算符显示为计划成本的99.7%(11.94327 / (11.94327 + 0.0332965)
)
答案 1 :(得分:1)
如果触摸的所有页面都在缓存中,则CPU成本和日志写入可能需要大约1ms或更短的时间。客户端库开销实际上可能在CPU方面比服务器负载更多。
对于不在缓存中的每个页面,您可以预期磁盘上的磁盘搜索量为5-10ms。粗略地说,您可以期望Table1
中的每个索引都会触及一个此类访问权限加上Table2
中的一个访问权限来验证FK。
执行计划告诉您确定要执行哪些物理操作。
700毫秒似乎很多(70个索引?!)。请发布实际的执行计划。服务器已卸载,由于锁定没有阻塞?