1、现象
一个很简单的查询语句select * from t1 order by 日期 查询花了25s,但是不加order by秒出
2、分析
我这里的原因是优化器因为语句简单执行了TRIVIAL模式,
SET STATISTICS XML ON; SELECT * FROM dbo.t1 ORDER BY 日期; SET STATISTICS XML OFF;执行后发现执行计划中
1.StatementOptmLevel="TRIVIAL"
优化器认为这个查询“太简单了”,根本没有认真优化。它跳过了大部分优化步骤,直接生成了一个“凑合能用”的计划。
2.SpillToTempDb SpillLevel="2"
排序操作内存不足,溢写(Spill)到了tempdb。这就是25秒延迟的直接原因——数据写入了磁盘,而不是在内存中完成排序。
3.GrantWaitTime="25003"
这正是25秒的来历!查询在等待内存授权(Memory Grant),等了整整25秒才获得足够的内存来执行排序。这个25秒不是排序耗时,而是“排队等内存”的耗时。
溢写的原因是SQL Server 的TRIVIAL优化模式,会在预估内存需求时使用非常保守的估算。对于这个查询,它只申请了512KB内存(SerialRequiredMemory="512"),但实际排序需要约8MB(SerialDesiredMemory="8152",因为24个字段大量varchar字段设置了255的长度最大行宽就是24 × 255 = 6120字节(加上一些开销,大约 6120 字节)),估算与实际严重不符,导致内存不足,触发了tempdb溢写和长时间的等待。
3、结论
在不改优化器策略的情况下的解决方案是只列需要查询的列