Nij*_*Nij 6 database sql-server performance sql-server-2008 sql-server-2008-r2
我有一个具有适当索引的查询,并显示在查询计划中,估计的子树成本约为1.5.该计划显示了一个Index Seup,然后是Key Lookup - 这对于一个预期从5到20行的一组中返回1行的查询很好(即Index Seek应该找到5到20行之间,以及5到20之后)关键查找,我们应该返回1行).
以交互方式运行时,查询几乎立即返回.但是,今天早上的数据库跟踪显示了来自live(一个Web应用程序)的运行时间变化很大; 通常,查询正在进行<100 DB Reads,并且有效地运行0 ...但是我们正在进行一些消耗> 170,000 DB Reads的运行,并且运行时间高达60s(大于我们的超时值).
什么可以解释磁盘读取的这种变化?我尝试以交互方式比较查询,并使用来自两个并行运行的实际执行计划,其中过滤值取自快速和慢速运行,但是交互式地显示这些计划在使用的计划中没有任何差异.
我还试图找出可以锁定这个查询的其他查询,但我不确定这会如何影响数据库读取......并且无论如何这个查询往往是我的跟踪日志中运行时最差的.
更新:以下是交互式运行查询时生成的计划示例:

请忽略"缺失索引"文本.这是事实,改变目前的指标可以允许用较少的查找更快的查询,但不是这里的问题(已经有合适的索引).这是一个实际执行计划,我们可以看到实际行数等数字.例如,在Index Seek上,实际行数为16,I/O成本为0.003.Key Lookup上的I/O成本相同.
更新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
Run Code Online (Sandbox Code Playgroud)
使用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());
Run Code Online (Sandbox Code Playgroud)
数据是否会从缓存中删除?这可能可以解释为什么使用热缓存(数据已经在内存中)时,记录的读取次数非常低......然后当数据不再位于 RAM 中时,读取次数会增加,因为它必须从磁盘上读取数据再次。
只需一个想法即可推动事情进展。