2

看看这个执行计划:http
://sdrv.ms/1agLg7K 不是估计的,是实际的。从大约30 分钟的实际执行中。

选择第二条语句(占用总执行时间的 47.8%——大约 15 分钟)。
查看该语句中的顶部操作 – View Clustered Index Seek over _Security_Tuple4。该操作花费了语句的 51.2%——大约 7 分钟。

该视图包含大约 0.5M 行(作为参考,log2(0.5M) ~= 19 - 考虑到索引树节点大小为 2,仅 19 步,实际上可能更高)。
该运算符的结果是零行(与估计不匹配,但暂时不要介意)。
实际执行 - 零。

所以问题是:哔哔声怎么可能需要七分钟?!(当然,我该如何解决?)


编辑关于我在这里问的一些澄清
我对一般性能相关的建议感兴趣,例如“查看索引”、“查看大小”、“参数嗅探”、“不同数据的不同执行计划”等。
我已经知道了所有这些,我可以做到所有这些分析我自己。

我真正需要的是知道什么会导致一个特定的聚集索引搜索如此缓慢,然后我可以做些什么来加快它

不是整个查询。
不是查询的任何部分。
只是一个特定的索引搜索。
结束编辑


还要注意第二个和第三个最昂贵的操作是如何分别在 _Security_Tuple3 和 _Security_Tuple2 上查找的,它们只需要 7.5% 和 3.7% 的时间。同时,_Security_Tuple3 包含大约 280 万行,是 _Security_Tuple4 的六倍。

另外,一些背景:

  1. 这是该项目中唯一一个行为不端的数据库。有几十个相同模式的其他数据库,它们都没有出现这个问题。
  2. 第一次发现这个问题时,发现索引99%是碎片化的。重建索引确实加快了速度,但并不显着:整个查询在重建前用了 45 分钟,在重建后用了 30 分钟。
  3. 在使用数据库时,我注意到像“select count(*) from _Security_Tuple4”这样的简单查询需要几分钟时间。怎么回事?!
  4. 然而,他们在第一次运行时只用了几分钟,然后就瞬间完成了。
  5. 问题连接到特定的服务器,也不连接到特定的 SQL Server 实例:如果我备份数据库然后在另一台计算机上恢复它,行为保持不变。
4

3 回答 3

3

首先我想在这里指出一个小误解:虽然据说删除语句占用了整个执行时间的近 48%,但这并不一定意味着它占用了所需时间的 48%;事实上,在查询计划的那一部分内分配的 51% 绝对不应该被解释为占用整个操作的“一半时间”!

无论如何,按照您的说法,“第一次”执行表的 COUNT(*) 需要几分钟,我倾向于说您有与所述表/视图相关的 IO 问题。就我个人而言,我不太喜欢物化视图,因此我对它们以及它们内部的行为方式没有真正的经验,但通常我会建议碎片化对底层存储系统造成损害。它第二次运行得很快的原因是因为从缓存中访问页面比从磁盘中获取页面要快得多,尤其是当它们到处都是。(视图中是否有(最大)字段?)

无论如何,要找出需要这么长时间的原因,我建议您宁愿将此代码从它当前所在的触发器中取出,“伪造”一个插入和删除的表,然后尝试再次运行查询,添加时间戳和/或使用SQL Sentry Plan Explorer 之类的程序可以查看每个部分真正需要多长时间(当您从程序中运行脚本时,它有一个持续时间列)。很可能是您看错了部分;经验表明,成本和实际执行时间并不总是像我们想的那样相关。

于 2013-09-12T19:48:25.220 回答
1

观察包括:

  1. 这是您正在使用的这些数据库中最大的一个吗?如果是这样,大小对优化器很重要。它将为大型数据集与较小的数据集制定完全不同的计划。
  2. 估计的行和实际的行有很大的不同。这在第四个查询中最为明显。“从@alternativeRoutes 中删除c ....”,其中_Security_Tuple5 估计返回16行,但实际上使用了235,904行。对于这么多行,索引扫描可能比索引搜索更高效。表上的统计数据是最新的还是需要更新?
  3. “从_Security_Tuple4 中选择计数(*)”需要几分钟,这是第一次。第二次是即时的。这是因为数据现在都缓存在内存中(直到它过期)并且第二个查询很快。
  4. 因为问题随着数据库而移动,所以统计信息、任何缺失的索引等都在数据库中。我还建议检查索引是否与使用相同架构的其他数据库匹配。

这不是一个完整的分析,但它给你一些东西看。

于 2013-09-03T18:28:12.107 回答
0

费奥多尔,

第一的:

问题不连接到特定的服务器,也不连接到特定的 SQL Server 实例:如果我备份数据库然后在另一台计算机上恢复它,行为保持不变。

我假设您:a)在隔离环境中运行此查询,b)数据未发生突变。

这个对吗?

第二:在此处发布您的 CREATE INDEX 脚本。你有一个有趣的填充因子吗?SORT_IN_TEMPDB?

第三:你的ParentId、ObjectId是什么类型?int、smallint、uniqueidentifier、varchar?

于 2013-09-11T14:30:38.573 回答