主键删除需要多长时间?

时间:2012-12-12 17:24:05

标签: sql-server performance sql-server-2008-r2 sql-delete

想象一个简单的表结构:

Table1        Table2
----------    ----------
ID<-------|   ID
Name      |-->Table1ID
              Name

Table1有几百万行(例如350万行)。我按主键发出删除:

DELETE FROM Table1 WHERE ID = 100;

Table2中没有行引用Table1 ID = 100,因此删除工作时不会违反任何外键约束。

您希望删除多长时间?大约几毫秒?几百毫秒?一秒钟还是更多?几秒钟?等等,假设机器没有陷入困境并随时处理请求。

现在,我有这种情况,这样的删除大约需要700毫秒。对我来说,这似乎太慢了。我很好奇,如果我离开基地,或者其他人都认为这太慢了,并建议帮助加快速度!

以下是实际执行计划:

Execution Plan

(此处为XML执行计划:http://pastebin.com/q9hSMLi3

聚集索引删除(81%)命中聚类PK,非聚类唯一索引和非聚类非唯一索引。

2 个答案:

答案 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个索引?!)。请发布实际的执行计划。服务器已卸载,由于锁定没有阻塞?