文章主要描述的是SQL Server聚集索引的指示(Cluster Index Indications),在實際操作中借助聚集索引來進行搜索行,在一般的情況下會比借助非聚集索引來搜索行快主要有兩個原因。原因一是聚集索引只包含了一個指向頁的指針而不是指向單個數據行的指針;
所以,一個聚集索引比非聚集索引更緊湊。因為SQL Server聚集索引更小並且不需要額外的書簽查找來發現匹配的行,而且比相似定義的非聚集索引可通過更少的頁的讀操作來發現行。
第二個原因是聚集索引的表中的數據物理上就是按照聚集鍵來存放,搜索重復值或者聚集鍵的一個范圍值更快;行之間相互鄰接並且SQL Server能簡單定位第一個滿足條件的行然後順序搜索直到發現最後一個滿足條件的行。然而,每個表上只能創建一個聚集索引,你必須明智地選擇在哪個列或哪些列上來定義聚集索引。
如果你要求在一個表上只創建一個單獨的索引,那創建SQL Server聚集索引有很大優勢;則結果就是在修改、插入和刪除時的負擔將比創建非聚集索引的負擔要小的多。
默認情況下,表中的主鍵將被定義為聚集的唯一索引。在大多數應用中,表上的主鍵列總是以單行查找的方式來檢索。對於單行查找,一個非聚集索引通常比一個相似的聚集索引花費更少的I/O代價。你或者你的用戶真正注意過讀三頁去檢索單個數據行和四到六頁去檢索單個數據行之間的區別嗎?不一定。然而,如果你執行一個范圍檢索,比如查找last name,你將會注意到掃描表的10%和使用全表掃描來發現行之間的區別嗎?一定會的。
根據這種思想,你可能想為你的主鍵創建一個唯一的非聚集索引,並選擇其他候選列做為你的聚集索引。下面就是一些指南,可以幫助你來選擇SQL Server聚集索引的潛在的候選者:
一些頻繁搜索的具有許多重復值的列,比如, where last_name = 'Smith' 因為數據物理上是有序的,所有的重復值將聚集在一起。任何一個對該鍵值的查詢將會用最小的I/O來發現所有的值。SQL Server 定位第一個滿足SARG的行,然後按順序掃描數據直到找到最後一個滿足SARG的行。
經常被ORDER BY子句指定的列。
因為數據已經是有序的,如果ORDER BY 是關於聚集索引的,那SQL Server將避免重新排序。記住:即使對一個表掃描,數據也將會按照聚集鍵值的順序檢索,因為數據表上的數據是按照聚集鍵值排序。
經常按照一個范圍值進行查詢的列,例如,Where price between ¥10 and ¥20 使用聚集索引首先定位第一個滿足范圍條件的行。因為表中的行按順序排列,SQL Server能簡單按順序掃描數據頁直到最後個滿足范圍的條件的行。當滿足條件的結果集非常大,從執行的邏輯I/O來講,SQL Server聚集索引掃描將比借助非聚集索引重復進行書簽查找更有效。
除了主鍵外,頻繁使用在join子句中的列。聚集索引趨向於比非聚集索引更小;每個查找需要頁的I/O一般來講比非聚集索引更少。當join許多記錄時這種區別將是巨大的。一兩個額外的讀頁操作好像對一個單行檢索來說不多,但是把這些額外的對100,000join迭代的讀頁操作相加,你會看到總共100,000到200,00讀頁操作。
選擇聚集索引鍵時應滿足四個特點:
Narrow(窄,即長度短)
Unique(唯一性)
Unchanging(不變化)
Ever increasing(不斷增長)
當你考慮聚集索引列時,你可能想嘗試在相對靜態的列上創建SQL Server聚集索引,來最小化由於索引列的修改而引起的數據行重新排序。任何時間當聚集索引的鍵值改變了,所有把聚集索引作為書簽的非聚集索引都需要被修改。
盡量避免在以單調形式插入的順序的鍵字段上創建聚集索引,比如一個標識列(identity column)。這會在表的末尾創建一個"熱點"(hot spot),結果會在表和索引的的末尾導致鎖競爭和死鎖。另外,聚集索引也不會重用以前數據頁中的空間,因為所有新的行都排在數據表的末尾。這種情況造成了空間的浪費和你的表的增長會比預期的要大。一般的建議是,盡量在一個有某種隨機分布的數據值上建立索引。盡量選擇一個使得插入和修改活動散布在整個表的聚集鍵。一些能夠使得數據隨機化的候選聚集索引包括下列:出生日期、Last name first name、郵編
一個隨機hash key(通常只當沒有其他實際列可以作為好的候選的SQL Server聚集索引時才使用)
在整個表上散布你的數據有助於最小化頁競爭,同時也提供了更有效的空間利用。如果序列鍵是你的主鍵,你仍能用一個唯一、非聚集索引來提供一個訪問路徑並維護主鍵的唯一性。
因為你只能以一種方式對表上的數據進行物理排序,你只能有一個聚集索引。你想索引的其它列只能被定義為非聚集索引。