复合非聚集索引里列的顺序的重要性
當我談?wù)撍饕龝r,大家經(jīng)常會問我在復(fù)合非聚集索引里,列的順序是否重要?簡單來說:“看情況”。我們來具體看下為啥“看情況”……
單例查找(Singleton Lookups)
當在你的表上有進行單例查找的查詢時,在復(fù)合非聚集索引里列的順序真的不重要。假設(shè)下列查詢:
-- 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現(xiàn)在你可以在StateProvinceID和City,或City和StateProvinceID創(chuàng)建非聚集索引:
-- 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在執(zhí)行計劃里直接進行非聚集索引查找操作(在與查找謂語集合里):
范圍掃描(Range Scans)
當我們討論在表上的范圍掃描時,這里你檢索一組數(shù)據(jù),就是另一回事了。假設(shè)你執(zhí)行下列查詢:
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這個情況下,如你在執(zhí)行計劃里所見,SQL在StateProvinceID列上對查詢進行非聚集索引查找操作,對于City列要計算剩余謂語的值:
這真的不是個完美的執(zhí)行計劃,因為你讀取了比你請求更多的數(shù)據(jù)。但有基于StateProvinceID列上的排序作為引導列,?City作為隨后列,這是唯一可能的行為,如你從下圖所見:
現(xiàn)在我們嘗試交換下列來創(chuàng)建非聚集索引:City作為引導列,StateProvinceID作為第二列:
-- 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當你再次執(zhí)行你的查詢,你會看到SQL Server再次執(zhí)行了非聚集索引查找操作。但這次對于你的查詢,“沒有”剩余謂語(Residual Predicate)。
因為你物理上讀取的剛好是你邏輯上請求的數(shù)據(jù)。但這個現(xiàn)在這么可能呢?那就看看下面的圖:在非聚集索引里數(shù)據(jù)是如何排序的:
如你所見,現(xiàn)在的數(shù)據(jù)按City預(yù)先排,在每個City組里,你會有在StateProvinceID列的排序。因此你可以直接獲得邏輯請求的數(shù)據(jù)——不用進一步剩余謂語(Residual Predicate)的值計算就可以返回值。
小結(jié)
當你要進行范圍掃描時——在復(fù)合非聚集索引里列的順序重要的!在多次交流會上我經(jīng)常提到:SQL Server里的一切幾戶都與索引有關(guān),索引本身就會預(yù)排序數(shù)據(jù)!沒別的!理解SQL Server是否可以直接查找邏輯請求的數(shù)據(jù),你也需要在你的心中想象下如何使如何預(yù)排序的,你如何通過有效預(yù)排序數(shù)據(jù)來訪問它。
希望這篇文章可以讓你更好的理解在非聚集索引里,列排序如何影響查找操作。
感謝關(guān)注!
轉(zhuǎn)載于:https://www.cnblogs.com/lykbk/p/hgfhffhfhfhfhhfhf678786886687.html
總結(jié)
以上是生活随笔為你收集整理的复合非聚集索引里列的顺序的重要性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面向对象的JavaScript-009-
- 下一篇: 线程安全的单例模式的几种实现方法分享