6

我有一个具有适当索引的查询,并显示在查询计划中,估计子树成本约为 1.5。该计划显示一个索引查找,然后是键查找 - 这对于预期从 5 到 20 行的集合中返回 1 行的查询很好(即索引查找应该在 5 到 20 行之间找到,并且在 5 到 20 行之后)键查找,我们应该返回 1 行)。

当以交互方式运行时,查询几乎立即返回。然而,今天早上的数据库跟踪显示来自实时(网络应用程序)的运行时差异很大;通常,查询需要 < 100 次 DB 读取,并且实际上是 0 运行时......但是我们得到了一些消耗 > 170,000 次数据库读取的运行,并且运行时间长达 60 秒(大于我们的超时值)。

什么可以解释磁盘读取的这种变化?我曾尝试以交互方式比较查询,并使用来自两个并行运行的实际执行计划以及从快速和慢速运行中获取的过滤器值,但交互地这些实际上显示所使用的计划没有区别。

我还尝试确定可能锁定此查询的其他查询,但我不确定这会对 DB 读取产生如此大的影响……无论如何,在我的跟踪日志中,该查询往往是运行时最糟糕的。

更新:这是交互式运行查询时生成的计划示例:

替代文字

忽略“缺少索引”文本。确实,对当前索引的更改可以通过更少的查找实现更快的查询,但这不是这里的问题(已经有适当的索引)。这是一个实际执行计划,我们在其中看到诸如实际行数之类的数字。例如,在 Index Seek 上,实际行数为 16,I/O 成本为 0.003。I/O 成本与 Key Lookup 相同。

更新 2:此查询的跟踪结果是:

exec sp_executesql N'select [...column list removed...] from ApplicationStatus where ApplicationGUID = @ApplicationGUID and ApplicationStatusCode = @ApplicationStatusCode;',N'@ApplicationGUID uniqueidentifier,@ApplicationStatusCode bigint',@ApplicationGUID='ECEC33BC-3984-4DA4-A445-C43639BF7853',@ApplicationStatusCode=10

该查询是使用 Gentle.Framework SqlBuilder 类构建的,该类构建参数化查询,如下所示:

SqlBuilder sb = new SqlBuilder(StatementType.Select, typeof(ApplicationStatus));
sb.AddConstraint(Operator.Equals, "ApplicationGUID", guid);
sb.AddConstraint(Operator.Equals, "ApplicationStatusCode", 10);
SqlStatement stmt = sb.GetStatement(true);
IList apps = ObjectFactory.GetCollection(typeof(ApplicationStatus), stmt.Execute());
4

2 回答 2

1

运行分析器以查看统计信息是否在同一时间更新。或者只是看看还有什么事情发生。

另外,请添加 SQL 查询以及客户端代码。

想法:

  • 听起来你的“5-20”行可能远不止这些
  • 使用糟糕的计划/参数嗅探,您将始终获得糟糕的性能
  • 这张表上的写入情况如何:足以更新统计信息?
  • 有一些数据类型问题吗?(例如连接参数和引入数据类型转换)
于 2010-09-10T04:12:29.127 回答
1

是否可以从缓存中删除数据?这可能可以解释为什么使用热缓存(数据已经在内存中),记录的读取非常低......然后当数据不再在 RAM 中时,读取会增加,因为它必须从磁盘读取它再次。

让事情动起来只有一个想法。

于 2010-09-09T12:43:25.430 回答