下面是本人畫的一張關於數據頁和索引存儲結構圖
此圖中,最上部分是數據頁的存儲結構。
下半部分是表中有索引,這里就出現了B-Tree結構,索引的根級會引用索引的下一級,直到索引的最后一級,這一級引用的對象是RID(當表中不存在聚集索引時,RID會指向每一行數據存儲位置,RID的字段長度為16字節)或聚集索引列(當表存在索引時,聚集索引指向每一行數據存儲位置)。
如果一個表每行存儲200個字符,那么一個8Kb頁面最多存儲8060/200=40行數據。如果索引的字段是20個字節,表中聚集索引字段為16個字節或者沒有聚集索引,那么索引行的長度為20+16=36個字節,每一個8Kb索引頁存儲索引的行數為8060/20=223行,也就是說:當數據小於223行時,索引只需要1個8Kb頁面,而數據則需要223/40=6個8Kb頁面。當數據大於223行時,索引頁會分頁,分成兩個索引頁,此時,會出現更高一級的索引節點,該節點引用它的下一級節點。此時,索引有2級,根級和子頁級。根級保存的是對子頁級的引用,此時,保存的數據最多為223*223行,如果數據繼續增加,那么根級會再次分頁並變成第一子頁級,同時生成新的根級,也就是上面圖的結果,這個時候索引有3級,存儲的最大數據為223*223*223。
當需要查詢一行數據所有的列時,查詢分析器只需要掃描4次就可以找數據。
注意:
1、 當表存在聚集索引時,並且只需要查詢聚集索引鍵值,而查詢條件使用到索引時,那么查詢一次只需要掃描3次則可以找到數據,因為不需要掃描數據頁級。如果查詢的是整行,則需要掃描4次,多出來的一次是掃描數據頁。
2、 當表不存在聚集索引時,查詢某列(非索引列)或整行數據時,查詢一次需要掃描4次才能找到數據,因為需要掃描數據頁。
如果沒有索引時,查找某一行數據,就需要逐行逐行的掃描,所以就會出現全表掃描或聚集索引掃描的情況。
上面的列子中,一個8kb數據頁最多只能存儲40行數據,而一個索引頁最多可以存儲223行數據,這里可以看出來索引的一個作用,縮小掃描的次數,用來提升性能。這就是以空間換取性能的結果。