概述
生產庫中sqlserver怎麼也占了三分之一,所以今天主要聊聊怎麼在sqlserver資料庫上去建索引。
1、索引概述
創建索引一般有以下兩個目的:維護被索引列的唯一性和提供快速訪問表中數據的策略。
大型資料庫有兩種索引即簇索引和非簇索引:
1)非簇索引的表是按堆結構存儲數據,所有的數據均添加在表的尾部;
2)簇索引的表,其數據在物理上會按照簇索引鍵的順序存儲,一個表只允許有一個簇索引。
因此,根據B樹結構,可以理解添加任何一種索引均能提高按索引列查詢的速度,但會降低插入、更新、刪除操作的性能,尤其是當填充因子(Fill Factor)較大時。所以對索引較多的表進行頻繁的插入、更新、刪除操作,建表和索引時因設置較小的填充因子,以便在各數據頁中留下較多的自由空間,減少頁分割及重新組織的工作。
索引是從資料庫中獲取數據的最高效方式之一。95% 的資料庫性能問題都可以採用索引技術得到解決。作為一條規則,我通常對邏輯主鍵使用唯一的成組索引,對系統鍵(作為存儲過程)採用唯一的非成組索引,對任何外鍵列[欄位]採用非成組索引。不過,索引就象是鹽,太多了菜就咸了。你得考慮資料庫的空間有多大,表如何進行訪問,還有這些訪問是否主要用作讀寫,(即:在實際使用當中,應該充分考慮到索引的開銷,包括磁碟空間的開銷及處理開銷(如資源競爭和加鎖)。如果數據頻繁的更新或刪加,就不宜建立索引)
實際上,可以把索引理解為一種特殊的目錄。微軟的SQL SERVER提供了兩種索引:聚集索引(clustered index,也稱聚類索引、簇集索引)和非聚集索引(nonclustered index,也稱非聚類索引、非簇集索引)。
2、聚集索引結構
在 SQL Server 中,索引是按 B 樹結構進行組織的。
聚集索引單個分區中的結構:
聚集索引(Clustered Index)特點:
- 聚集索引的葉節點就是實際的數據頁
- 聚集索引中的排序順序僅僅表示數據頁鏈在邏輯上是有序的。而不是按照順序物理的存儲在磁碟上
- 行的物理位置和行在索引中的位置是相同的
- 每個表只能有一個聚集索引
- 聚集索引的平均大小大約為表大小的5%左右
3、非聚集索引結構
非聚集索引與聚集索引具有相同的 B 樹結構,它們之間的顯著差別在於以下兩點:
- 1. 基礎表的數據行不按非聚集鍵的順序排序和存儲。
- 2. 非聚集索引的葉層是由索引頁而不是由數據頁組成。
下圖示意了單個分區中的非聚集索引結構:
非聚集索引 (Unclustered Index) 特點:
- 非聚集索引的頁,不是數據,而是指向數據頁的頁。
- 若未指定索引類型,則默認為非聚集索引。
- 葉節點頁的次序和表的物理存儲次序不同
- 每個表最多可以有249個非聚集索引
- 在非聚集索引創建之前創建聚集索引(否則會引發索引重建)
4、聚集索引和非聚集索引的區別
其實,我們的漢語字典的正文本身就是一個聚集索引。比如,我們要查「安」字,就會很自然地翻開字典的前幾頁,因為「安」的拼音是「an」,而按照拼音排序漢字的字典是以英文字母「a」開頭並以「z」結尾的,那麼「安」字就自然地排在字典的前部。如果你翻完了所有以「a」開頭的部分仍然找不到這個字,那麼就說明你的字典中沒有這個字;同樣的,如果查「張」字,那你也會將你的字典翻到最後部分,因為「張」的拼音是「zhang」。也就是說,字典的正文部分本身就是一個目錄,你不需要再去查其他目錄來找到你需要找的內容。
我們把這種正文內容本身就是一種按照一定規則排列的目錄稱為「聚集索引」。
如果你認識某個字,你可以快速地從自動中查到這個字。但你也可能會遇到你不認識的字,不知道它的發音,這時候,你就不能按照剛才的方法找到你要查的字,而需要去根據「偏旁部首」查到你要找的字,然後根據這個字後的頁碼直接翻到某頁來找到你要找的字。但你結合「部首目錄」和「檢字表」而查到的字的排序並不是真正的正文的排序方法,比如你查「張」字,我們可以看到在查部首之後的檢字表中「張」的頁碼是672頁,檢字表中「張」的上面是「馳」字,但頁碼卻是63頁,「張」的下面是「弩」字,頁面是390頁。很顯然,這些字並不是真正的分別位於「張」字的上下方,現在你看到的連續的「馳、張、弩」三字實際上就是他們在非聚集索引中的排序,是字典正文中的字在非聚集索引中的映射。我們可以通過這種方式來找到你所需要的字,但它需要兩個過程,先找到目錄中的結果,然後再翻到你所需要的頁碼。
我們把這種目錄純粹是目錄,正文純粹是正文的排序方式稱為「非聚集索引」。
進一步引申一下,我們可以很容易的理解:每個表只能有一個聚集索引,因為目錄只能按照一種方法進行排序。
兩者的存儲特點:
- 聚集索引。表數據按照索引的順序來存儲的,也就是說索引項的順序與表中記錄的物理順序一致。對於聚集索引,葉子結點即存儲了真實的數據行,不再有另外單獨的數據頁。 在一張表上最多只能創建一個聚集索引,因為真實數據的物理順序只能有一種。
- 非聚集索引。表數據存儲順序與索引順序無關。對於非聚集索引,葉結點包含索引欄位值及指向數據頁數據行的邏輯指針,其行數量與數據表行數據量一致。
總之,聚集索引是一種稀疏索引,數據頁上一級的索引頁存儲的是頁指針,而不是行指針。而對於非聚集索引,則是密集索引,在數據頁的上一級索引頁它為每一個數據行存儲一條索引記錄。
5、使用 聚集索引 或 非聚集索引 的場景
下面的表總結了何時使用聚集索引或非聚集索引:
總結
「水可載舟,亦可覆舟」,索引也一樣。索引有助於提高檢索性能,但過多或不當的索引也會導致系統低效。因為用戶在表中每加進一個索引,資料庫就要做更多的工作。過多的索引甚至會導致索引碎片。
所以說,我們要建立一個「適當」的索引體系,特別是對聚合索引的創建,更應精益求精,以使資料庫能得到高性能的發揮。
覺得有用的朋友多幫忙轉發哦!後面會分享更多devops和DBA方面的內容,感興趣的朋友可以關注下~