索引列顺序和扫描而不是查找

Index columns order and Scan instead of seek

请考虑 Northwind 数据库中的 Customer table:

我在 3 列上添加索引:

CREATE NONCLUSTERED INDEX [idx_1] ON [dbo].[Customers]
    ([CompanyName] ASC, [City] ASC, [Country] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, 
      ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

我测试了这些查询:

1) SELECT CompanyName,city,country FROM [Northwind].[dbo].[Customers] where CompanyName='a' and city='b' and country='c'

2) SELECT CompanyName,city,country FROM [Northwind].[dbo].[Customers] where country='c' and CompanyName='a' and city='b'

3) SELECT CompanyName,city,country FROM [Northwind].[dbo].[Customers] where CompanyName='a' and country='c'

4) SELECT CompanyName,city,country FROM [Northwind].[dbo].[Customers] where CompanyName='a' and city='b'

以上所有查询都使用 Index Seek

是否有这些谓词正确?

A) 如果我的索引有 N 列,那么这些 N 列与其值相等的所有排列都使用 Index Seek因此,当所有列都参与 Where 子句时,Index 中的列顺序并不重要。

B) 如果我的索引有 N 列(例如:Col1, Col2, Col3,...) then all these combinations inWhereclause useIndex Seek`:

B-1) Col1, Col2,
B-2) Col1, Col2, Col3
B-3) Col1, Col3, Col4
B-4) Col1, Col4, Col7

所以Col1使用Index Seek很重要。

请考虑这个查询:

5) SELECT CompanyName,city,country, PostalCode FROM [Northwind].[dbo].[Customers] where CompanyName='a' and city='b' and country='c'

C) 我在Select列表中添加了PostalCode,为什么Index Seek转换为Index Scan?为什么 Seek 没有转换为 Seek + Key Lookup

1) 列顺序很重要,因为索引键是使用指定的列顺序构造的。因此,只有在谓词中包含 CompanyName 列(就像在所有 WHERE 子句中一样),才能有效地进行索引查找(而不是扫描)。列在谓词中的顺序无关紧要 - 查询优化器将确定是否指定了必要的列以执行查找。

2) 同样,需要包含 Col1,因为这是为索引指定的第一列,因此构成了索引键的开头。

3) 添加 PostalCode 意味着索引不再涵盖提供查询所需的所有列。然后由查询优化器来评估索引查找或索引扫描是否更有效。这将取决于许多因素,但一个重要的因素是它估计谓词将返回多少行,因此相对于扫描 table(聚簇索引)。很明显,在这种情况下,聚簇索引的扫描效率更高。