数据库读取在带有索引的查询上变化很大
Posted
技术标签:
【中文标题】数据库读取在带有索引的查询上变化很大【英文标题】:Database reads varying dramatically on a query with indexes 【发布时间】:2010-09-09 12:29:34 【问题描述】:我有一个具有适当索引的查询,并显示在查询计划中,估计子树成本约为 1.5。该计划显示一个索引查找,然后是键查找 - 这对于预期从 5 到 20 行的集合中返回 1 行的查询很好(即索引查找应该在 5 到 20 行之间找到,并且在 5 到 20 行之后)键查找,我们应该返回 1 行)。
以交互方式运行时,查询几乎立即返回。然而,今天早上的数据库跟踪显示来自实时(网络应用程序)的运行时差异很大;通常,查询需要 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());
【问题讨论】:
【参考方案1】:可以从缓存中删除数据吗?这可能可以解释为什么使用热缓存(数据已经在内存中),记录的读取非常低....然后当数据不再在 RAM 中时,读取会增加,因为它必须从磁盘读取它再次。
只需一个想法就能让事情动起来。
【讨论】:
我不这么认为;我的理解是,即使从缓存中检索到逻辑磁盘读取,分析也会显示逻辑磁盘读取。不过,我不确定。【参考方案2】:运行分析器以查看统计信息是否在同一时间更新。或者只是看看还有什么情况。
另外,请添加 SQL 查询以及客户端代码。
想法:
听起来您的“5-20”行可能远不止于此 如果计划/参数嗅探不当,您的性能会一直很差 如何在此表上发生写入:足以更新统计信息? 是否存在一些数据类型问题? (例如连接参数和引入数据类型转换)【讨论】:
@gbn:据我所知,所涉及的索引的统计数据大约在 3 天前更新(我们有一份强制它的工作)。我添加了查询计划的屏幕截图(交互运行时)。我不相信存在数据类型问题。这是一个经常添加记录的表(在身份 PK 上)...我需要做一些研究,在什么情况下这可能会强制更新统计信息,以及是否会在查询的读取下显示。 @Nij:这个计划显然没问题(好吧,可以被覆盖)并且在这里没有帮助......它是有用的 SQL 代码和客户端代码。 @gbn:查询显示在上方的屏幕截图中。当您说客户端代码时,我并不是 100% 理解您的意思,但如果您指的是 C# 源代码之类的东西,我不确定这会如何影响数据库读取? @Nij:这就是你如何参数化我感兴趣的 SQL 查询 @gbn:上面的另一个更新。我认为我们在代码方面没有做任何特别不寻常的事情。但是由于我们使用的(非常旧的)ORM; Gentle.Framework,对于如何提交这个查询,我们没有真正的选择。以上是关于数据库读取在带有索引的查询上变化很大的主要内容,如果未能解决你的问题,请参考以下文章