2011-03-25 138 views
2

嗨,我是新來的SQL,我想知道如果有人可以告訴我在同一列使用羣集和非集羣索引。我在我的工作中查看了一些表腳本,但不明白在一列上同時使用了集羣索引和非集羣索引的用途。它是一個ID列,它位於數據庫中的所有表中。索引問題

+0

假設您正在談論SQL Server,我們是否正確? – 2011-03-25 20:51:01

+0

是的sql,謝謝... – Programmer 2011-03-25 20:56:27

+1

'SQL'只是**結構化查詢語言** - 它不是**產品** - 沒有數據庫系統。你指的是微軟的** SQL Server ** - 一個具體的數據庫產品。 – 2011-03-25 21:19:43

回答

2

在一個非常簡單的術語中,CLUSTERED和NON CLUSTERED INDEX之間的區別在於,CLUSTERED索引是表中記錄的物理順序,基於索引字段中的值,而非CLUSTERED索引是邏輯根據索引字段中的值排序表中的記錄。這個邏輯順序是由SQL數據庫引擎根據表中值的統計分佈決定的。

另一個重要的區別是,對於一個表,只能有一個CLUSTERED索引(因爲它是存儲在該表中的數據的物理順序)。雖然您可以在同一個表上的不同字段上有許多不同的非聚簇索引。

就這麼說,當然你可以在表的同一個字段上同時使用CLUSTERED和NON CLUSTERED索引,這很有用,因爲通常CLUSTERED索引特別擅長順序訪問數據,而非CLUSTERED索引可以針對隨機進行優化SQL數據庫引擎訪問數據。通過這種方式,同一列上的CLUSTERED和NON CLUSTERED索引組合使您能夠在基於索引字段中的值進行搜索時高度優化對該表中記錄的訪問。

+0

這並不能解釋爲什麼你會在同一列上有NCI和CI。這兩個索引的非葉級頁面幾乎是相同的,所以當用特定的id查找時,對隨機訪問沒有特別的好處(特別是考慮到NCI使用CI鍵作爲行定位器,所以CI將* *仍然**必須被遍歷!)。也不保證它們是物理順序(碎片)。它們都是按照邏輯順序排列的,下一頁和上一頁由頁頭中的字段表示。 – 2011-03-27 00:59:51

+0

@Martin在NCI/CI情況下,通過一個ID查找單個行幾乎沒有什麼區別。在這種情況下,如果ID列在數據庫的所有表中,可能是錯誤的或者它可能是正確的,很難知道這些ID是否代表相同的事情。這聽起來像是一種代碼味道,但也有合法的原因。如果OP忽略NCI包含列(並且它成爲特定查詢的覆蓋範圍),該怎麼辦?然後,NCI掃描可能會優先於此表上的表掃描。 – 2011-03-27 13:48:24

+0

@Cade - 是的,這是真的。我注意到我原來的評論中有一個錯誤。非葉頁當然不會像CI那樣可能有更多的頁面,所以樹會越來越深,但是NCI的任何查找都不得不遍歷CI。 – 2011-03-27 13:53:41

4

聚集索引並不是一個真正的索引 - 從某種意義上說,它是根據鍵在樹中組織的所有數據。

非聚集索引只是樹中的關鍵字,其中包含任何附加的列以及必要的書籤,以便在必要時進入數據行。數據本身可以存儲在聚簇索引或堆中。可以有許多非聚集索引,但顯然只有一種真正的選擇來存儲數據的方式。

對於特定查詢的執行情況,堆上的覆蓋非聚簇索引(或任何,無關緊要,因爲索引正在覆蓋)通常可以輕鬆地勝過聚簇索引,因爲索引可能適合更多每頁行數,並且不需要書籤查找就可以將數據從行中取出,而聚集索引seek/scan將讀取並丟棄更多數據,並且每頁的行數更少。

通常,您需要聚簇索引,並且聚簇鍵應該是窄的,靜態的,增加的,唯一的。

但是,對於查詢性能,您真的想查看非聚簇索引,並選擇覆蓋並在適用的情況下將正確方向的排序順序。

+0

你還沒有給出任何用例,說明你爲什麼在一個'id'列上有一個NCI和一個CI。我可以想象一個'id'上的狹窄索引可能對某些類型的查詢很有用,比如半連接,或者強制外鍵約束 - 不能真的想到其他用例嗎? – 2011-03-27 01:06:11

+0

@Martin一個具有單個id且不包含列的NCI仍然會更快地進行存在驗證,然後是id上的配置項,因爲每個頁面都會包含更多數據(假設表格相對較寬)。但是,你是對的,這種情況只適用於id是外鍵的情況,例如FK到符合特定條件的行的另一個表。一般來說,被覆蓋的NCI將是首選。在這種情況下,書籤和CI的選擇是無關緊要的,因爲索引覆蓋。當然,你應該有一個CI,但不要依賴它來讀取性能。 – 2011-03-27 13:40:52