我對DB的接觸有限,只使用DB做爲應用程序程序員。 我想了解Clustered
和Non clustered indexes
。 我搜索了一下,發現的是: 程序員
彙集索引是一種特殊的索引,它從新排序表中記錄的物理存儲方式。 所以,表只能有一個彙集索引。 彙集索引的葉節點包含數據頁。 非彙集索引是一種特殊類型的索引,其中索引的邏輯順序與磁盤上行的物理存儲順序不匹配。 非彙集索引的葉節點不包含數據頁。 相反,葉節點包含索引行。 sql
我在SO中發現的是彙集索引和非彙集索引之間的區別是什麼? 。 數據庫
有人能夠用簡單的英語解釋嗎? 數組
彙集索引意味着您要告訴數據庫在磁盤上存儲實際上彼此接近的關閉值。 這具備快速掃描/檢索落入彙集索引值範圍內的記錄的好處。 app
例如,您有兩個表Customer和Order: dom
Customer ---------- ID Name Address Order ---------- ID CustomerID Price
若是但願快速檢索一個特定客戶的全部訂單,則可能但願在「訂單」表的「客戶ID」列上建立聚簇索引。 這樣,具備相同CustomerID的記錄將在物理上彼此靠近存儲在磁盤上(成簇),從而加快了檢索速度。 ui
PS客戶ID上的索引顯然不是惟一的,所以您要麼須要添加第二個字段來「統一」索引,要麼讓數據庫爲您處理該索引,但這是另外一回事了。 spa
關於多個索引。 每一個表只能有一個彙集索引,由於它定義了數據的物理排列方式。 若是您想打個比方,請想象一個有不少桌子的大房間。 您能夠將這些表造成幾行,也能夠將它們所有拉在一塊兒以造成一個大會議表,但不能同時使用兩種方法。 一個表能夠有其餘索引,它們將指向彙集索引中的條目,而彙集索引又將最終說出在哪裏能夠找到實際數據。 指針
使用匯集索引時,行將以與索引相同的順序物理存儲在磁盤上。 所以,只能有一個聚簇索引。 code
使用非彙集索引時,第二個列表具備指向物理行的指針。 您能夠有許多非彙集索引,儘管每一個新索引都會增長寫入新記錄所需的時間。
若是要取回全部列,一般從彙集索引中讀取會更快。 您沒必要先進入索引,而後再進入表。
若是須要從新排列數據,則寫入具備彙集索引的表的速度可能會變慢。
一個很是簡單的,非技術性的經驗法則是,彙集索引一般用於主鍵(或至少是惟一列),而非彙集索引用於其餘狀況(也許是外鍵) 。 實際上,默認狀況下,SQL Server將在您的主鍵列上建立聚簇索引。 正如您將學到的,彙集索引與磁盤上數據的物理排序方式有關,這意味着在大多數狀況下,它是一個很好的全面選擇。
在下面找到彙集索引和非彙集索引的一些特徵:
create Index index_name(col1, col2, col.....)
。 在SQL Server面向行的存儲中,彙集索引和非彙集索引都組織爲B樹。
( 圖片來源 )
彙集索引和非彙集索引之間的主要區別在於,彙集索引的葉級是表。 這有兩個含義。
非彙集索引也能夠經過使用INCLUDE
子句(自SQL Server 2005開始)明確包含全部非鍵列來進行第1點的操做,可是它們是輔助表示,而且周圍始終有另外一個數據副本(表自己)。
CREATE TABLE T ( A INT, B INT, C INT, D INT ) CREATE UNIQUE CLUSTERED INDEX ci ON T(A,B) CREATE UNIQUE NONCLUSTERED INDEX nci ON T(A,B) INCLUDE (C,D)
上面的兩個索引幾乎相同。 上級索引頁面包含鍵列A,B
值,葉級頁面包含A,B,C,D
每一個表只能有一個彙集索引,由於數據行自己只能以一種順序排序。
上面SQL Server在線叢書中的引用引發不少混亂
我認爲最好用這樣的措辭。
每一個表只能有一個彙集索引,由於彙集索引的葉級行是錶行。
聯機叢書的報價並不正確,可是您應該清楚非彙集索引和彙集索引的「排序」是邏輯上而非物理上的。 若是您經過遵循連接列表來讀取葉級頁面,並以插槽數組順序讀取頁面上的行,則您將以排序的順序讀取索引行,但實際上頁面可能未排序。 一般認爲,使用匯集索引時,行老是以與索引鍵相同的順序物理存儲在磁盤上,這是錯誤的。
這將是荒謬的實現。 例如,若是某行插入到4GB桌子中間的SQL Server 沒有在文件中的數據拷貝2GB高達騰出空間給新插入的行。
而是發生頁面拆分。 聚簇索引和非聚簇索引的葉級上的每一個頁面都有按邏輯鍵順序排列的下一頁和上一頁的地址( File:Page
)。 這些頁面沒必要是連續的或按鍵順序排列的。
例如,連接的頁面鏈多是1:2000 <-> 1:157 <-> 1:7053
當發生頁面拆分時,將從文件組中的任何位置分配新頁面(從混合範圍(對於小型表),或者屬於該對象的非空統一範圍或新分配的統一範圍)。 若是文件組包含多個文件,則該文件甚至可能不在同一文件中。
邏輯順序和連續性與理想物理版本不一樣的程度是邏輯碎片的程度。
在一個只有一個文件的新建立的數據庫中,我運行了如下命令。
CREATE TABLE T ( X TINYINT NOT NULL, Y CHAR(3000) NULL ); CREATE CLUSTERED INDEX ix ON T(X); GO --Insert 100 rows with values 1 - 100 in random order DECLARE @C1 AS CURSOR, @X AS INT SET @C1 = CURSOR FAST_FORWARD FOR SELECT number FROM master..spt_values WHERE type = 'P' AND number BETWEEN 1 AND 100 ORDER BY CRYPT_GEN_RANDOM(4) OPEN @C1; FETCH NEXT FROM @C1 INTO @X; WHILE @@FETCH_STATUS = 0 BEGIN INSERT INTO T (X) VALUES (@X); FETCH NEXT FROM @C1 INTO @X; END
而後使用
SELECT page_id, X, geometry::Point(page_id, X, 0).STBuffer(1) FROM T CROSS APPLY sys.fn_PhysLocCracker( %% physloc %% ) ORDER BY page_id
結果處處都是。 按鍵順序的第一行(值1-用下面的箭頭突出顯示)幾乎在最後一個物理頁面上。
經過重建或從新組織索引以增長邏輯順序和物理順序之間的相關性,能夠減小或消除碎片。
跑步後
ALTER INDEX ix ON T REBUILD;
我獲得如下
若是表沒有聚簇索引,則稱爲堆。
非彙集索引能夠創建在堆索引或彙集索引上。 它們始終包含返回到基表的行定位器。 對於堆,這是物理行標識符(rid),由三個組件(File:Page:Slot)組成。 對於聚簇索引,行定位符是邏輯的(聚簇索引鍵)。
對於後一種狀況,若是非聚簇索引已經天然地包括CI鍵列(做爲NCI鍵列或INCLUDE
-d列),則不添加任何內容。 不然,缺乏的CI鍵列將被靜默添加到NCI中。
SQL Server始終確保兩種索引類型的鍵列都是惟一的。 可是,對於未聲明爲惟一的索引,強制執行此機制的機制在兩種索引類型之間有所不一樣。
聚簇索引會爲具備重複現有行的鍵值的任何行添加一個uniquifier
。 這只是一個遞增的整數。
對於未聲明爲惟一的非彙集索引,SQL Server會將行定位符靜默添加到非彙集索引鍵中。 這適用於全部行,而不只僅是實際重複的行。
聚類命名法與非聚類命名法也用於列存儲索引。 本文對SQL Server列存儲的加強狀態
儘管列存儲數據並無真正「彙集」在任何鍵上,但咱們仍是決定保留傳統的SQL Server約定,即將主索引稱爲聚簇索引。