InnoDB 是按照索引來存儲數據的;用戶數據都存儲在聚簇索引中;
每個索引有自己的數據空間,一個索引會有兩個獨立的空間(段 segment),一個段用來存儲非葉子節點索引數據,一個段用來存儲葉子節點數據;
段又會細分為64個塊(extend - 1MB),每個塊是由256個頁(page - 16KB)組成,頁編號在表空間中獨立存儲的,4個字節(32位),所以一個表空間大致可以存儲64TB;
理論上來說每個段是一塊獨立連續的物理空間,主要是為了加載數據,方便進行順序遍歷數據,隨機IO代價比較高,雖然底層頁支持存儲空間不是連續的;
為了方便段中數據管理,又將區分為3類:空閑、滿和非滿,組成3個鏈表,來實現數據的更改的管理;
數據插入都是先進入空閑和非滿的碎片區,這些區暫時不屬於某個段,(效率比較高);
當碎片區達到32個頁,會對區進行遷移,將碎片區區分配到某個段下面;
頁是最小的數據單元,讀取數據時,都是一整頁讀入內存;
為了提高查詢速度,又會將頁中的記錄數據進行分組,每4-8條分為一組,每組的最小值(索引列的值)形成一個鏈表;
索引形成的B+樹,聚簇索引會按照 (主鍵、所在頁最小值、其他列數據(葉子節點))為單元,主鍵大小排序形成一顆樹,每一層數據都是以頁為單位存儲;
普通二級索引,葉子節點就不會存儲每條記錄的詳細信息了,只會存儲記錄的主鍵信息,類似:
所以二級索引如果不能查詢的數據不能覆蓋索引,那么就需要通過二級索引查詢聚簇索引,在通過聚簇索引查詢數據記錄;簡稱回表;
總結:
索引主要思想是:將數據排序分組,然后將邊界值再重新組成一個新的組,組中的數據以鏈表的方式連接;
通過二分查找的方式來快速定位數據所在的頁;
本文參考 掘金小冊:MySQL是怎樣運行的