複合非彙集索引——列順序重要麼?

當我談論索引時,你們常常會問我在複合非彙集索引裏,列的順序是否重要?簡單來講:「看狀況」。咱們來具體看下爲啥「看狀況」……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

相關文章
相關標籤/搜索