很多人對索引都沒有一個清晰的認識,對於聚集索引和非聚集索引之間的區別也不是很清楚。如果有人問我索引是什么,我覺得這個問題有點大,很難在一篇文章里解釋清楚。所以我決定嘗試寫這一系列文章,用一個簡單的,可以理解的方法解釋索引,盡管網上關於索引的文章有一籮筐那么多。
簡單來說,索引幫助數據庫引擎使用最小的資源,最高效的找到需要的數據。通過唯一列索引可以保證數據的連貫性,當索引不一定要建在唯一列上。在忙碌的系統里,通過增加並發操作,可以提高性能。在一個表上建立的各個索引可以滿足不同用戶的請求,但這也是個頭疼的問題。索引保存在不同的頁,就像數據存在不同的地方,SQL Server要保證它們的一致性。對表的任何INSERT,UPDATE,DELETE操作,對應的索引頁會執行相同的操作。索引幫助我們提高獲取數據的性能,但對DML操作卻是個麻煩。在DELETE和UPDATE里,索引會幫助數據庫引擎找到需要修改的記錄。一個表要建多少個索引並沒有訣竅(thrumb rule)。如果你要更好的讀性能,你可以創建更多的索引,如果你要更好DML操作性能,請保持最小數量的索引。
SQL Server支持2類索引:
- 聚集索引(Clustered Index:CI)
- 非聚集索引(Non Clustered Index:NCI)
讓我們用現實生活中的例子來理解這2類索引。假設你的鄰居到你家,問你“Woody Tu”的電話號碼。在這種情況下,電話本目錄就是個聚集索引。你打開電話本目錄,跳過3/4的頁,假定他的名字應該出現在目錄的最后一部分。在前后翻過幾頁后,你找到了列有“Woody Tu”名字的頁。現在你就可以把號碼告訴你的鄰居了。看看這里發生了什么?當你找到了列有“Woody Tu”名字的頁時,你就有了你鄰居(客戶端)需要的信息。
我們再看另一個情況,你的鄰居到你家,問你“Woody Tu”的電子郵件地址,而你並不記得。在這個情況下,電話本目錄會扮演非聚集索引的角色。你打開電話本目錄,跳過3/4的頁,假定他的名字應該出現在目錄的最后一部分。在前后翻過幾頁后,你找到了列有“Woody Tu”名字的頁。現在你可以打電話給“Woody Tu”,問下他的電子郵件地址是多少。掛下電話后,你可以把他的電子郵件地址交給你的鄰居。看看這里發生了什么?當你找到了列有“Woody Tu”名字的頁時,你並沒有鄰居(客戶端)需要的信息。你需要去做一個額外操作(打電話)來獲得鄰居(客戶端)需要的信息。在SQL Server里,這個額外操作被稱為書簽/RID查找(Bookmark or RID Lookup,注:RID,堆的行標識符(FileID:PageID:SlotNumber))。
希望這個介紹可以讓你對聚集索引和非聚集索引有了感性的認識。在接下來的文章里,我們會討論聚集索引和非聚集索引的更多細節。