2017-09-13 115 views
2

我有關於SQL Server索引的問題,這些索引一直在困擾着我。在非聚集索引中,第二,第三,第四...列是如何排序的?

想象一下,一個表是這樣的:

CREATE TABLE TelephoneBook (
    FirstName nvarchar(50), 
    LastName nvarchar(50), 
    PhoneNumber nvarchar(50) 
) 

有這樣一個指標:

CREATE NONCLUSTERED INDEX IX_LastName ON TelephoneBook (
    LastName, 
    FirstName, 
    PhoneNumber 
) 

和想象,這個表有幾十萬行的。

比方說,我想選擇姓氏以B開頭,名字是'John'的人。我會寫下面的查詢:

SELECT 
    * 
FROM TelephoneBook 
WHERE LastName like 'B%' 
AND FirstName='John' 

由於索引可以幫助減少我們需要掃描,因爲這組所有反正用B開始LastNames的行數,它也爲做到這一點名字?或者數據庫掃描以B開頭的每一行以找到名爲'John'的那一行?

換句話說,第二,第三,第四,...列是如何在索引中排序的?在這種情況下它們是否也是字母順序的,所以很容易找到約翰娜?或者他們是以某種隨機或不同的順序?

編輯:爲什麼我問,是因爲我剛纔讀到,在上面的SELECT語句中,索引只會用於縮小搜索範圍,以姓氏以B開始的記錄,但索引將會不能用於找到Johanna所有的行(並且會掃描所有'B'行)。我想知道這是爲什麼?我沒有得到什麼?

回答

2

作爲一種便利的速記,索引的關鍵字用於where子句,直至第一個不等式。帶有通配符的like被認爲是不等式。

因此,索引只會用於查找第一個值。但是,條目可能會被掃描以匹配名字,所以您仍然會獲得索引使用。

當然,如果決定全表掃描更合適,優化器可能決定不使用索引。

+0

對小表進行全表掃描的成本要低於在同一個表上對非聚集索引的查找。我已經看到人們強制索引使用25個行表,因爲全表掃描是不好的。很酷的答案 – Namphibian

1

戈登的答案在這個例子中是正確的,並帶有指定的查詢。一般而言,您應該意識到,它並不是根據列的值將「記錄」中的記錄組合在一起,而是根據索引的關鍵列對其進行排序。換句話說,您在此索引中的記錄將按照LastName排序,對於共享相同LastName值的記錄,它們將按FirstName值進一步排序,然後按PhoneNumber值進行排序。您沒有爲此索引中的列指定排序順序,但是SQL Server defaults unspecified sort orders to ASC(ending),因此這些列在索引中確實按詞彙順序排序。正如Gordon的回答所提到的那樣,查詢優化器決定查看第一列的索引以確定要抓取哪些記錄,但是如果優化器決定更好,SQL Server將重新排列謂詞,根據查詢本身和您正在查詢的記錄的統計信息,可能會使用索引的更多列或根本沒有。

0

從邏輯上講,索引按鍵值順序排列。因此,在這種情況下,LastName(按文本排序),FirstName(以文本形式排列),然後是PhoneNumber(按文本排序)...任何包含的列根本不排序。

在你的情況中,我們知道尾隨通配符仍然是SARGable,所以我們希望看到索引將數據縮小到所有數據w/LastNames從w /「B」開始,從該數據池開始將被進一步過濾以僅包含具有FirstName ='John'的那些行。你可以把它看作索引搜索,然後是範圍搜索。

相關問題