2009-05-06
5.2 Clustered Indexes(叢集索引) (page 122)
叢集索引決定了一個表數據的物理排列順序,所以,一個表隻能有一個叢集索引。圖5.1表示了一個叢集索引的結構。
Figure 5.1
The structure of a clustered index
一個叢集索引的最底層(the lowest level)由它的數據頁(data pages)組成. 叢集索引的數據頁叫做這個索引的葉節點(leaf level of the index)。索引的其它部分則由索引頁(index pages)組成。最頂層的索引頁叫做索引的根節點(index root)。介於葉節點與根節點的索引頁,叫做中間頁(intermediate-level pages).
索引中每個層級的分頁都是鏈接在一起的。索引頁上的每個項目都包含一個鍵值(key value),以及一個指向下一個索引頁的最底層(the lowest level)的指針。叢集索引的指針就是一個頁號(page number),再加上一個檔案ID(File ID)作為前綴,這是因為頁號僅在同一個數據庫檔案中是唯一的。一個檔案ID再加上一個頁號,就組成了一個頁ID(page ID).
那麼,SQL Server查詢優化器如何使用叢集索引來獲取數據的呢?
1. 返回單一數據行
SELECT * FROM customers WHERE customer_lname = 'Green'
首先,SQL Server從系統表sysindexes表中取得表customers的根頁(root page),在這個範例中,如圖5.1所示,它的根頁是42. 根頁中可能會有很多個鍵值,SQL Server將會找到不大於Green的最大的那個鍵值,在圖5.1中,這個值為ADAMS,它所對應的指針,即頁號(page number)為58,所以頁號為58的索引頁將會被獲得。
因為58頁仍然為索引頁,所以SQL Server會繼續在該頁中尋找大不於Green的那個鍵值,從圖5.1中可以看到,這個值為DATE,它所對應的指針指向頁號337,337頁為數據頁,這樣,SQL Server將會掃描337頁以得到並返回Green的數據。需要注意的是,在獲得數據頁之前,SQL Server並不知道該行數據是否存在。
本次查詢所耗用的I/O次數共三次:查詢根頁42一次,中間頁58一次,最後讀取數據頁337又一次。
2. 返回一個範圍的數據行
SELECT * FROM customers
WHERE customer_lname BETWEEN 'Date' AND 'Kirk'
因為叢集索引將欄位dustomer_lname按鍵值排序,所以一個範圍內的數據一定會放在一起,在圖5.1中,滿足該查詢的數據在337,338,339這三個頁號中,所以,三次I/O就可以獲得該查詢的結果集共6行。
假設一個數據頁可以存儲15行cumstomers表的數據,那麼,8次I/O就可以讀取15*8=120行數據。如果沒有叢集索引的話,對這些行的訪問可能會引起120次I/O.
5.3 Non-clustered Indexes (非叢集索引) (page 127)
與叢集索引類似,非叢集索引的頂部是root page(根頁),底部是leaf-level page(葉級頁),中間的是中間頁(intermediate-level page)。
沒有叢集索引的表的數據頁是沒有鏈接在一起的,即使這個表有非叢集索引也是如此。這種表的數據頁通過IAM頁來管理。
非叢集索引對資料表資料的物理排列順序沒有影響,它的底部的葉級頁也不是數據頁,而是索引頁。圖5.3表示了一個非叢集索引的結構,並且它所在的表沒有叢集索引。
Figure 5.3
Structure of a nonclustered index when no clustered index on the table
從圖中可以看到,這個表中的每一個數據頁都有一個指針從非叢集索引的葉級頁指向它,與叢集索引不同,非叢集索引的葉級頁隻包含指向每個數據頁的最小鍵值的指針,這就意味著非叢集索引一般情況下要比叢集索引大,因為非叢集索引的葉級頁必須包含很多指針。還是依前面談及的例子,假設一個數據頁可以儲存customers表15行數據,那麼這個非叢集索引的葉級頁就需要儲存多於叢集索引葉級頁15倍的指針。這樣一來,非叢集索引要比叢集索引多一層索引頁。
與叢集索引類似,非叢集索引的每個條目都是包含一個鍵值,一個指向它的下一個索引頁的最小鍵值的指針。這種指針是一個頁ID(File ID+ database page number)。 但非叢集索引的葉級頁上的指針就可能有所不同。如果它所在的表沒有建立叢集索引的話,那麼它的葉級頁上的指針就是一個行ID(Row ID)。一個行ID是由頁ID加上行號組成的(A row ID is a page ID plus a row number)。舉例來說,圖5.3上的葉級頁96上的Ben,它的頁ID是是1:340,行號為2.
從圖5.3上可以看出,雖然非叢集索引的索引頁是順序排列的,但數據頁卻不是。這就意味著如果使用非叢集索引進行範圍讀取的話,將會為每個相關的葉級頁的指針執行一次邏輯讀取(logical read)以抵達所需要的資料行(data rows)。
5.4 Online indexes (在線索引) (page 129)
使用SQL Server的在線索引功能建立或者重建索引時,該索引上正在執行的查詢或者修改動作無需等待索引建立完成,而是繼續使用原有的結構直至索引建立.