1. 程式人生 > >金萬城平臺SQL Server索引的原理深入解析扣892118

金萬城平臺SQL Server索引的原理深入解析扣892118

主鍵 page 有一個 就是 返回 刪除數據 數據 註意 name

1.1 聚集索引
表的數據是存儲在數據頁中(數據頁的PageType標記為1),SqlServer一頁是8k,存滿一頁就開辟下一頁存儲。如果表有聚集索引,那麽一筆一筆物理數據就是按聚集索引字段的大小升/降排序存儲在頁中。當對聚集索引字段更新或中間插入/刪除數據時,都會導致表數據移動(造成性能一定影響),因為它要保持升/降排序。

註意,主鍵只是默認是聚集索引,它也可以設置為非聚集索引,也可以在非主鍵字段上設置為聚集索引,全表只能有一個聚集索引。
一個優秀的聚集索引字段一般包含以下4個特性:
(A).自增長
總是在末尾增加記錄,減少分頁和索引碎片。
(B).不被更改
減少數據移動。
(C).唯一性
唯一性是任何索引最理想的特性,可以明確索引鍵值在排序中的位置。

更重要的是,索引鍵指唯一的話,它在每條記錄裏才可以正確指向源數據行RID。如果聚集索引鍵值不唯一,SqlServer就需要內部生成uniquifier 列組合當作聚集鍵保證“鍵值”唯一性;如果非聚集索引鍵值不唯一,就會增加RID列(聚集索引鍵或者堆表中的行指針)保證“鍵值”唯一性。
思考(可略過):索引“鍵值”在非葉子節點也有保證唯一性,原因應該是為了明確索引記錄在非葉子節點中的位置。比如有個非聚集索引字段Name2,表中有很多Name2=‘a‘的記錄,導致Name2=‘a‘在非葉子節點上有多條索引記錄(節點),這時候再insert一筆Name2=‘a‘的記錄時,就可以根據非葉子節點的RID和新增記錄的RID很快確定要insert到哪個索引記錄(節點)上,如果沒有非葉子節點的RID,那得遍歷到所有Name2=‘a‘的葉子節點才能確定位置。另外,當我們select * from Table1 where Name2<=‘a‘時,返回的數據是按非聚集索引Name2和RID排序的,很好理解返回的數據就是按這邊索引存儲的順序排序的。這是這條sql查詢時有用到Name2索引的結果,如果數據庫查詢計劃因“臨界點”問題選擇直接表數據掃描,那返回的數據默認就是按表數據的順序排序的。
為了“鍵值”唯一性,對於聚集索引,uniquifier 列只在索引值重復時增加。對於非聚集索引,如果創建索引時沒定義唯一,RID會在所有記錄增加,就算索引值是唯一的;如果創建索引時定義唯一,RID只在葉子層增加,用於查找源數據行,即書簽查找操作。
(D).字段長度小
聚集索引鍵長度越小,一頁索引頁就可以容納更多索引記錄,進而減少索引B樹結構的深度。例如,一個百萬記錄的表有一個int聚集索引,可能只需要3層的B樹結構。如果把聚集索引定義在更寬的列(比如uniqueidentifier列需要16 字節),那麽索引的深度會增加到4層。任何聚集索引查找需要4個I/O操作(確切的說是4個邏輯讀),原先只要3個I/O操作。
同樣,非聚集索引裏會包含聚集索引鍵值,聚集索引鍵長度越小非聚集索引記錄也就越小,一頁索引頁就可以容納更多索引記錄。

金萬城平臺SQL Server索引的原理深入解析扣892118