我正在使用SQL Server 2008 R2数据库,其中的表包含十亿行的顺序。我想在过去24小时内获得一列的不同值,所以我这样做(查询1):
SELECT DISTINCT SomeField FROM SomeTable WHERE CreatedOn > '2014-01-28 12:24:00'
请注意 CreatedOn 上有一个索引,但它不包含 SomeField 。这立即返回。现在,由于这是我经常运行的查询,我决定将其设置为动态,因此我将其更改为(查询2):
DECLARE @StartDate DATETIME = DATEADD(DAY, -1, GETDATE())
SELECT DISTINCT SomeField FROM SomeTable WHERE CreatedOn > @StartDate
我很惊讶这个查询花了很长时间。 (我在一分钟左右后停止了它。)然后我尝试将变量内联这样(查询3):
SELECT DISTINCT SomeField FROM SomeTable WHERE CreatedOn > DATEADD(DAY, -1, GETDATE())
那又快了。查看执行计划,查询1和3是相同的,并使用索引查找。但是查询2执行了索引扫描并建议我在CreatedOn上缺少索引,包括SomeField。
为什么检查变量会突然改变索引的有效性?
答案 0 :(得分:1)
最可能的原因是,当值被硬编码时,编译器可以使用统计信息来确定要运行的最佳查询。使用变量时,它不会也不必进行扫描。如果您尝试创建存储过程并且以这种方式运行,那么服务器可以使用“parameter sniffing”,您可能会看到更好的性能。