不可持久查询是否可以使用非聚集索引?

时间:2018-07-08 05:23:03

标签: sql-server

我正在浏览基于SQL Server 2012(现在为SQL Server 2014)的070-461 MS图书,发现此查询部分指出不应使用非聚集索引,因为我们未使用SARGs语法在WHERE谓词中。

SELECT orderid, custid, orderdate, shipname
FROM Sales.Orders
WHERE DATEDIFF(day, '20060709', orderdate) <= 2
  AND DATEDIFF(day, '20060709', orderdate) > 0;

此处的链接支持相同:What makes a SQL statement sargable?

我在SQL Server 2014上测试了完全相同的查询,并且使用非聚集索引(好像它可以存储)确实看到了它

我找不到任何表明SQL Server 2014中已更改的内容,或者SARG会接受列

关于我所缺少的任何想法吗?

这是本书的屏幕截图:

enter image description here

这里是我使用SQL Server 2014的实验室的屏幕截图

enter image description here

1 个答案:

答案 0 :(得分:1)

是的,不可保留的查询可以使用非聚集索引。不可扩展的表达式阻止对索引执行查找操作,但是它允许索引扫描。

SQL Server 2014中的基数估计量已更改,我想这就是查询计划更改的原因。

如您在查询计划中看到的那样,该查询仍然不可保留,它完全扫描该索引。如果它是可存储的,或者SQL Server足够聪明,可以将谓词转换为可存储的表达式,则它会寻找索引。

SQL Server可以通过两种不同的方式解决查询:

方法1:

  1. 扫描聚簇索引,按日期过滤结果。想象一下 群集有25页。 IO成本是读取25页的成本。

方法2:

  1. 扫描非聚簇索引,按日期过滤结果。这个 索引比聚集索引小得多,因为它仅 包含日期和订单ID(集群键)列。想象一下它有6个 页面。 IO成本是读取6页的成本。的结果 该索引扫描是相应的聚簇键orderid。
  2. 键查找在步骤1中找到的每个订单编号,以获取列custid和shipname。想象一下,它找到2个orderid,然后必须执行两次关键查找。密钥查找每个需要2到4页读取。因此,关键查找最多需要8页读取。

因此,方法1需要25个逻辑读取,而方法2需要14个逻辑读取。方法2比方法1更有效。

但是,仅当与谓词匹配的行数足够小且索引大小差异足够大时,方法2才比方法1更有效。例如,如果有10个匹配的行,则需要6 + 10 * 4 = 46,这比方法1所需的逻辑读取还要多。

如果SQL Server 估计匹配行的数量足够小并且非聚集索引比聚集索引更小,SQL Server将选择方法2。

SQL Server更改了SQL Server 2014上的基数估计量,因此这可能是查询计划更改的原因。