我有以下查询,大约需要2分钟才能返回输出。
DECLARE @today DATETIME
SET @today = GETDATE()
SELECT con.*
FROM GAS_consumptions con
WHERE con.createdDate >= @today
我注意到如果我使用它,则需要不到一秒的时间
SELECT con.*
FROM GAS_consumptions con
WHERE con.createdDate >= '2015-06-22'
为什么会这样?我需要第一个查询,因为日期可能每天都有所不同。
答案 0 :(得分:1)
在查询中使用文字值时,SQL Server将生成针对该特定值进行优化的查询计划。
例如,如果您在createdDate上有非聚集索引,则查询优化器可以使用createdDate >= '2015-06-22'
获得对行数的良好估计。如果表中的一小部分行,最佳查询将在createdDate索引中找到匹配的记录,然后从表中查找匹配行的其余所选列。
在WHERE子句中使用变量时,SQL Server会生成一个查询计划,该计划将用于@today的所有可能值。生成的计划最适合@today的任意值,但单个计划只能对选定的特定行数最佳。
假设所选平均行数的估计值是表中行数的一半,在这种情况下,估计扫描整个表以过滤记录而不是过滤createdDate索引然后更高效必须在表上进行大量查找才能获得剩余的所选列。
问题是SQL Server对可能具有完全不同的行计数的查询使用单个查询计划。单个查询计划用于@today的所有值的原因通常是编译最佳查询比仅运行次优查询更昂贵。在你的例子中,显然情况并非如此。
有一些方法可以改变这种行为:
1)您也可以让Sql Server生成单个计划,但要根据预定的@today值进行优化
DECLARE @today DATETIME
SET @today = GETDATE()
SELECT con.*
FROM GAS_consumptions con
WHERE con.createdDate >= @today
OPTION (OPTIMIZE FOR (@today = '2015-06-22'))
这应该产生与使用con.createdDate >= '2015-06-22'
谓词相同的查询,并且如果您的应用程序总是在预定日期之后查询记录,则可以提供一个很好的解决方案。
2)指定重新编译选项将导致每次运行时生成新的查询计划,这允许针对特定的@today值优化查询。
DECLARE @today DATETIME
SET @today = GETDATE()
SELECT con.*
FROM GAS_consumptions con
WHERE con.createdDate >= @today
OPTION (RECOMPILE)
这应该产生与使用con.createdDate >= '2015-06-22'
谓词相同的查询。
警告:重新构建查询也可能会变慢。使用RECOMPILE选项可以降低性能。使用最后的度假村。 ETC。
答案 1 :(得分:0)
这只是一种解决方法。应用此commnad:
UPDATE STATISTICS GAS_consumptions WITH FULLSCAN, NORECOMPUTE
做几分钟的查询 再次陷入困境。
请记住,, NORECOMPUTE
将定期执行此命令,因为它会停止sqlserver将来生成统计信息的方式。
在我得到的类似案例中,这是“解决方案”。我不知道为什么会发生