查询中过滤器的顺序应该是什么,以优化查询以使用索引

Sha*_*pta 4 sql-server indexing performance query-optimization

我几乎没有怀疑.我从一些同事那里听说,如果我们在下表中创建了复合Nonclustured索引,那么所有过滤器的顺序应该是Indexed列,然后是Filter.

MyTable(T1,T2,T3,T4,T5)
非Clustured指数(T1,T2),顺序T1然后T2

问题

  1. 哪个查询更快?

  2. Indexed列的顺序会影响性能吗?

  3. 索引列是否应该首先优化查询?

  4. 处理查询的顺序是什么.处理查询时首先使用哪个过滤器?它是从Last过滤器开始并继续进行第一次过滤吗?

查询1

Select * from MyTable WHERE T1=1 AND T2=2 AND T3=1 
--(Indexing will be used) Fastest as T3 has been included after indexed columns
Run Code Online (Sandbox Code Playgroud)

查询2

Select * from MyTable WHERE T2=1 AND T1=2 AND T3=1
--(No Indexing will be used)
Run Code Online (Sandbox Code Playgroud)

查询3

Select * from MyTable WHERE T3=1 AND T1=1 AND T2=2
--(Indexing will be used) slower than Query 1 as indexed columns included afterwards
Run Code Online (Sandbox Code Playgroud)

查询4

Select * from MyTable WHERE T3=1 AND T2=1 AND T1=2
--(No Indexing will be used) slower than Query 2 as indexed columns occurs after non indexed column condition
Run Code Online (Sandbox Code Playgroud)

编辑:

查询5

Select * from MyTable WHERE T3=1 AND T2=1
Run Code Online (Sandbox Code Playgroud)

查询6

Select * from MyTable WHERE T3=1 AND T1=1 
Run Code Online (Sandbox Code Playgroud)

查询7

Select * from MyTable WHERE T3=1 AND T2=1 OR T1=2
Run Code Online (Sandbox Code Playgroud)

查询8

SSMS索引创建中的以下顺序意味着什么,即哪个过滤器应该首先出现?

替代文字

当我试图改变索引列中显示的列的顺序时.我看到Bookmark查找正在增加,并且正在使用Clustured索引扫描.但是当我使用图像中显示的相同顺序时.然后删除了书签查找,并获得了Index Seek.所以我可以看到索引中列的顺序在这里扮演了一些重要的角色但却无法理解.

Mar*_*ith 6

查询中谓词的顺序没有区别!

在考虑复合索引中的列顺序时,通常的类比是电话簿.这是按(姓氏,名字)排序的.这样可以直接查看姓氏,但不会帮助您按姓名查找数字.

如果你有一个索引(T1,T2),它可以用来有效地回答

Select * from MyTable WHERE T1=2
Run Code Online (Sandbox Code Playgroud)

要么

Select * from MyTable WHERE T2=1 AND T1=2
Run Code Online (Sandbox Code Playgroud)

但不是要有效地回答

Select * from MyTable WHERE T2=1
Run Code Online (Sandbox Code Playgroud)

(这并不是说这个索引总是对这个查询完全没用.如果索引与表的大小相比较窄,并且统计信息表明将返回很少匹配的行,查询优化器可能仍然选择扫描此索引和键查找优先于可能需要覆盖更多页面的聚簇索引扫描.)

根据评论示例脚本

CREATE TABLE MyTable  (
ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
T1 INT NOT NULL,
T2 INT NOT NULL,
Filler CHAR(8000) NOT NULL /*Just to make sure that the table is very wide!*/);

CREATE NONCLUSTERED INDEX IX ON MyTable (T1,T2);

   WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
        E02(N) AS (SELECT 1 FROM E00 a, E00 b),
        E04(N) AS (SELECT 1 FROM E02 a, E02 b),
        E08(N) AS (SELECT 1 FROM E04 a, E04 b),
        E16(N) AS (SELECT 1 FROM E08 a, E08 b),
        E32(N) AS (SELECT 1 FROM E16 a, E16 b),
   cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
 INSERT INTO MyTable 
 SELECT N, N-1,''
   FROM cteTally
  WHERE N <= 1000;

 SET STATISTICS IO ON
 Select * from MyTable  WHERE T2=1
 /*
 Table 'MyTable'. Scan count 1, logical reads 9, physical reads 0, 
 read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
 */

 /*Force a clustered index scan just to compare...*/
 Select * from MyTable   WITH( INDEX (1) ) WHERE T2=1 
/*
Table 'MyTable'. Scan count 1, logical reads 1005, physical reads 0, 
read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.*/
Run Code Online (Sandbox Code Playgroud)

计划