繁体   English   中英

执行计划索引用法

[英]Execution plan index usage

我尝试在一些我经常使用的查询中优化索引的使用。 最近,我了解到在where子句中使用函数和隐式转换不是最佳方法。 令我惊讶的是,由于正确使用了索引,隐式转换会更快。

我有一个称为记录的表。 聚集索引和主键位于Id列(int),非聚集索引位于Created列(datetime)。 为了避免隐式转换,我创建了@dd变量。

declare @dd Datetime

set @dd = '2019-08-25'

--1st option
select  * from Records where Created > @dd
--2nd option
select  * from Records where Created > '2019-08-25'    
--3rd option
select  * from Records where Year(Created) = 2019 and MONTH(Created) = 8 and DAY(Created) = 25

不幸的是,第一个选项使用索引扫描(列ID)。 第二个选项使用索引查找(创建的列)和键查找,这很好,但我想知道为什么第一个选项不做相同的事情。 我添加了第3个选项只是为了看到区别,它的行为就像第一个选项。

我已经找到查询执行计划:缺少索引 ,导致有关此行为的博客文章,但没有解释为什么会发生。 我可以看到估计的行数有所不同。 当我将日期设置为'2019-06-25' ,所有三个选项都使用类似的计划进行索引扫描。

因此,当我可以预期行数会很低时,使用隐式转换是否是经验法则? 我在这里很困惑。

由于T-SQL没有日期时间文字的语法,因此需要日期时间文字的隐式转换。 这与性能无关。

如果由于数据类型的优先级 (例如,将int文字与varchar列进行比较)而导致表达式无法精简,则隐式转换会引起关注。 YEAR函数应用于列也将导致表达式无法生成,因为必须在比较之前对函数结果求值。

查询中的问题是您使用的是变量而不是参数。 您应该获得与文字相同的性能:

select * from Records where Created > @dd OPTION(RECOMPILE);

或参数化查询(假设缓存的计划尚不存在):

EXEC sp_executesql N'select * from Records where Created > @dd'
    , N'@dd datetime'
    , @dd = '2019-08-25';

通过使用文字,参数和带有变量的OPTION(RECOMPLE) ,SQL Server在初始编译期间使用统计直方图(如果存在)以更好地估计可能返回的行数。 对于变量,SQL Server使用平均密度统计信息来估计行数。 结果可能会使用不同的计划,尤其是在数据分布偏斜的情况下。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM