复合非汇集索引——列顺序重要么?

当我谈论索引时,你们常常会问我在复合非汇集索引里,列的顺序是否重要?简单来讲:“看状况”。咱们来具体看下为啥“看状况”……sql

单例查找(Singleton Lookups)

当在你的表上有进行单例查找的查询时,在复合非汇集索引里列的顺序真的不重要。假设下列查询:spa

-- Without a supporting Non-Clustered Index we have to scan the complete Clustered Index
SELECT AddressID FROM Person.Address
WHERE StateProvinceID = 79 AND City = 'Bothell'
GO

如今你能够在StateProvinceIDCity,或CityStateProvinceID建立非汇集索引:code

-- Create a supporting Non-Clustered Index
CREATE NONCLUSTERED INDEX idx_Test ON Person.Address(StateProvinceID, City)
GO

-- SQL Server performs a Non-Clustered Index Seek operation in combination with a Seek Predicate
SELECT AddressID FROM Person.Address
WHERE StateProvinceID = 79 AND City = 'Bothell'
GO

-- Change the column ordering
CREATE NONCLUSTERED INDEX idx_Test ON Person.Address(City, StateProvinceID)
WITH (DROP_EXISTING = ON)
GO

-- The column ordering doesn't matter in the Non-Clustered Index
SELECT AddressID FROM Person.Address
WHERE StateProvinceID = 79 AND City = 'Bothell'
GO

这里非汇集索引里的列的顺序真的不重要,由于SQL Server在执行计划里直接进行非汇集索引查找操做(在与查找谓语集合里):orm

范围扫描(Range Scans)

当咱们讨论在表上的范围扫描时,这里你检索一组数据,就是另外一回事了。假设你执行下列查询:blog

SELECT AddressID FROM Person.Address
WHERE StateProvinceID BETWEEN 10 AND 12 AND City = 'Bothell'
GO

此次,支持的非汇集索引,你有2个方法:排序

  • StateProvinceID和City列上的非汇集索引
  • City和StateProvinceID列上的非汇集索引

咱们先用第一个方法:索引

-- Create a supporting Non-Clustered Index
CREATE NONCLUSTERED INDEX idx_Test ON Person.Address(StateProvinceID, City)
GO

这个状况下,如你在执行计划里所见,SQL在StateProvinceID列上对查询进行非汇集索引查找操做,对于City列要计算剩余谓语的值:get

这真的不是个完美的执行计划,由于你读取了比你请求更多的数据。但有基于StateProvinceID列上的排序做为引导列, City做为随后列,这是惟一可能的行为,如你从下图所见:it

如今咱们尝试交换下列来建立非汇集索引:City做为引导列,StateProvinceID做为第二列:io

-- Change the column ordering in the Non-Clustered Index
CREATE NONCLUSTERED INDEX idx_Test ON Person.Address(City, StateProvinceID)
WITH (DROP_EXISTING = ON)
GO

-- Non-Clustered Index Seek on StateProvinceID *without* a Residual Predicate on column City
SELECT AddressID FROM Person.Address
WHERE StateProvinceID BETWEEN 10 AND 12 AND City = 'Bothell'
GO

当你再次执行你的查询,你会看到SQL Server再次执行了非汇集索引查找操做。但此次对于你的查询,“没有”剩余谓语(Residual Predicate)。

由于你物理上读取的恰好是你逻辑上请求的数据。但这个如今这么可能呢?那就看看下面的图:在非汇集索引里数据是如何排序的:

如你所见,如今的数据按City预先排,在每一个City组里,你会有在StateProvinceID列的排序。所以你能够直接得到逻辑请求的数据——不用进一步剩余谓语(Residual Predicate)的值计算就能够返回值。

小结

当你要进行范围扫描时——在复合非汇集索引里列的顺序重要的!在屡次交流会上我常常提到:SQL Server里的一切几户都与索引有关,索引自己就会预排序数据!没别的!理解SQL Server是否能够直接查找逻辑请求的数据,你也须要在你的心中想象下如何使如何预排序的,你如何经过有效预排序数据来访问它。

但愿这篇文章可让你更好的理解在非汇集索引里,列排序如何影响查找操做。

感谢关注!

原文连接

https://www.sqlpassion.at/archive/2016/06/27/composite-non-clustered-indexes-does-the-sorting-order-matter

相关文章
相关标签/搜索