數據組織方式
在InnoDB存儲引擎中,表數據都是根據主鍵順序組織存放的,這種存儲方式的表稱為索引組織表(index organized table IOT)。
行數據,都是存儲在聚集索引的葉子節點上的。而我們之前也講解過InnoDB的邏輯結構圖:
在InnoDB引擎中,數據行是記錄在邏輯結構 page 頁
中的,而每一個頁的大小是固定的,默認16K。那也就意味著, 一個頁中所存儲的行也是有限的,如果插入的數據行row在該頁存儲不下,將會存儲到下一個頁中,頁與頁之間會通過指針連接。
頁分裂
頁可以為空,也可以填充一半,也可以填充100%。每個頁包含了2-N行數據(如果一行數據過大,會行溢出),根據主鍵排列。
A. 主鍵順序插入效果
-
從磁盤中申請頁, 主鍵順序插入:
-
第一個頁沒有滿,繼續往第一頁插入:
-
當第一個也寫滿之后,再寫入第二個頁,頁與頁之間會通過指針連接:
-
當第二頁寫滿了,再往第三頁寫入:
B. 主鍵亂序插入效果
- 假如1#,2#頁都已經寫滿了,存放了如圖所示的數據:
此時再插入id為50的記錄,我們來看看會發生什么現象:
會再次開啟一個頁,寫入新的頁中嗎?
不會。因為索引結構的葉子節點是有順序的。按照順序,應該存儲在47之后。
但是47所在的1#頁,已經寫滿了,存儲不了50對應的數據了。 那么此時會開辟一個新的頁 3#。
但是并不會直接將50存入3#頁,而是會將1#頁后一半的數據,移動到3#頁,然后在3#頁,插入50。
移動數據,并插入id為50的數據之后,那么此時,這三個頁之間的數據順序是有問題的。 1#的下一個頁,應該是3#, 3#的下一個頁是2#。 所以,此時,需要重新設置鏈表指針。
上述的這種現象,稱之為 “頁分裂”,是比較耗費性能的操作。
頁合并
目前表中已有數據的索引結構(葉子節點)如下:
當我們對已有數據進行刪除時,具體的效果如下:
當刪除一行記錄時,實際上記錄并沒有被物理刪除,只是記錄被標記(flaged)為刪除并且它的空間變得允許被其他記錄聲明使用。
當我們繼續刪除2#的數據記錄:
當頁中刪除的記錄達到 MERGE_THRESHOLD1(默認為頁的50%),InnoDB會開始尋找最靠近的頁(前或后)看看是否可以將兩個頁合并以優化空間使用。
刪除數據2,并將頁合并之后,再次插入新的數據20,則直接插入3#頁。
這個里面所發生的合并頁的這個現象,就稱之為 “頁合并”。
MERGE_THRESHOLD
:合并頁的閾值,可以自己設置,在創建表或者創建索引時指定。 ??此時數據才被物理刪除。 ??