4

画一个简单的表结构:

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、非聚集唯一索引和非聚集非唯一索引。

4

2 回答 2

4

问题是用于验证外键的聚集索引扫描。

当删除成功并且没有匹配的记录会导致违规时,则table2需要扫描所有记录。该表有 1,117,190 行,因此这是一项代价高昂的操作,绝对可以从索引中受益。

执行计划中显示的 10% 数字只是基于某些建模假设的估计。

整个计划的成本为0.0369164表 2 的扫描成本0.0036199为 ,其余的一切都占0.0332965. 但是请注意,对于聚集索引扫描运算符,Estimated CPU Cost is1.22907和 Estimated IO Cost is 10.7142(totaling 11.94327not 0.0369164)。

这种差异的原因是扫描在反半连接运算符下,一旦找到匹配的行,扫描就会停止。估计的子树成本在建模假设下按比例缩小,这将在仅扫描很小比例的表后发生。

如果没有 FK 违规并且删除成功,则需要扫描整个表,因此使用未按比例缩小的数字会提供更多信息。

如果使用11.94327代表实际发生的完整扫描的运算符的成本重新计算百分比,则此扫描运算符显示为计划成本的 99.7% ( 11.94327 / (11.94327 + 0.0332965))。

于 2012-12-12T18:41:29.550 回答
1

如果所有被触摸的页面都在缓存中,那么 CPU 成本和日志写入的时间大约为 1 毫秒或更短。就 CPU 而言,客户端库开销实际上可能比服务器负载更多。

对于不在缓存中的每个页面,您可以期望在磁盘上进行 5-10 毫秒的磁盘寻道。粗略地说,您可以期望每个被触及的索引一次这样的访问Table1加上一次访问Table2以验证 FK。

执行计划明确地告诉您要执行哪些物理操作。

700 毫秒似乎很多(70 个索引?!)。请张贴实际执行计划。服务器被卸载并且没有因为锁而阻塞?

于 2012-12-12T17:27:08.240 回答