got*_*tqn 6 sql t-sql sql-server sql-server-2012
我有存储过程,它根据输入参数构建动态SQL语句,然后执行它.
其中一个查询导致超时,所以我决定检查它.执行问题语句的第一次(也是第一次)它很慢(30秒-45秒),每次下一次执行需要1-2秒.
为了重现这个问题,我正在使用
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
Run Code Online (Sandbox Code Playgroud)
我真的很困惑,问题出在哪里,因为普通的如果SQL语句很慢,它总是很慢.现在,它只是第一次执行时间很长.
是可能的,本身是缓慢的,需要优化还是问题可能是由别的东西造成的?
执行计划如下,但对我来说没有什么奇怪的:

从您对我的评论的回复来看,该查询第一次运行时似乎执行了大量物理读取或预读读取,这意味着需要大量 IO 才能将正确的页面放入缓冲池以满足这个查询。
一旦页面被读入缓冲池(内存),它们通常会留在那里,以便不需要物理 IO 再次读取它们(您可以看到这种情况正在发生,因为您表明第二次查询时物理读取转换为逻辑读取正在运行)。内存比磁盘 IO 快几个数量级,因此该查询的速度存在差异。
查看该计划,我几乎可以看到每个读取操作都是针对表的聚集索引完成的。由于聚集索引包含行的每一列,因此每行获取的数据可能比查询实际需要的数据多。
除非您从每个表中选择每一列,否则我建议创建满足此查询的非聚集覆盖索引(尽可能窄),这将减少查询的 IO 要求,并使其第一次成本更低圆形的。
当然,这对您来说可能是不可能/不可行的,在这种情况下,您应该只在第一次运行时命中而不清空缓存,或者重写查询本身以提高效率并执行更少的读取。