【Mysql】InnoDb行格式、數據頁結構以及索引底層原理分析


在這裏插入圖片描述

我們用JDBC 等連接MySQL 其實就是,jdbc是客戶端來連接MySQL服務器。

Mysql服務器中負責對錶中數據的讀取和寫入工作的部分是存儲引擎,支持的存儲引擎就是倒數第二行的innobd、memory、myisam等。
存儲引擎的上一層是 處理數據的, 下一層是真的文件系統。

InnoDB

我們要講的是innodb,它是將表中的數據存儲到磁盤上的存儲引擎。

InnoDB存儲引擎不需要一條一條的把記錄從磁盤上讀出來,InnoDB採取的方式是:

  • 將數據劃分爲若干個頁,以頁作爲磁盤和內存之間交互的基本單位
  • InnoDB中頁的大小一般爲 16 KB
    也就是說,當需要從磁盤中讀數據時每一次最少將從磁盤中讀取16KB的內容到內存中,每一次最少也會把內存中的16KB內容寫到磁盤中

InnoDB數據頁結構

每次InnoDB拿的頁即數據頁,爲16kb,這16kb大小的存儲空間可以被劃分爲多個部分,示意圖如下:
在這裏插入圖片描述

  • 名稱 中文名 佔用空間 簡單描述
    File Header 文件頭部 38字節 頁的一些通用信息
    Page Header 頁面頭部 56字節 數據頁專有的一些信息
    Infimum + Supremum 最小記錄和最大記錄 26字節 兩個虛擬的行記錄
    User Records 用戶記錄 不確定 實際存儲的行記錄內容
    Free Space 空閒空間 不確定 頁中尚未使用的空間
    Page Directory 頁面目錄 不確定 頁中的某些記錄的相對位置
    File Trailer 文件尾部 8字節 校驗頁是否完整

InnoDB 行格式

我們平時是以記錄爲單位向表中插入數據的,這些記錄在磁盤上的存放方式被稱爲行格式。

行格式分別是Compact、Redundant、Dynamic和Compressed行格式

Compact

在這裏插入圖片描述

  • 記錄的真實數據:
    記錄的真實數據除了我們自己定義的列的數據外,還加了隱藏列:

    列名 是否必須 佔用空間 描述
    row_id 6字節 行id,唯一標識一條記錄
    transaction_id 6字節 事務id
    roll_pointer 7字節 回滾指針

    InnoDB對主鍵的生成策略
    優先使用用戶自定義主鍵作爲主鍵,如果沒定義,則選取一個unique鍵作爲主鍵,如果沒有定義unique鍵,則會爲表默認添加一個row_id 作爲主鍵.
    行溢出
    一頁只能存16kb, 而一個varchar的類型的列最多就可以存65533個字節,這樣就會造成一頁存不了一條記錄.
    在Compact和Reduntant格式中, 記錄真實數據數據處只會存儲該列的一部分數據,把剩餘的數據分散存儲在其他幾個頁中,記錄指向這些頁的地址.



  • 行格式除了記錄真實數據外,還會記錄額外信息:

    • 變長字段長度列表
      比如我們有varchar[varchar是可變長度的,所以佔用空間不確定] ,這裏就會記錄這個varchar對應的真實的長度

    • NULL值列表
      把這行數據裏是null的都記錄下來. 具體就是將每個允許存儲null的列對應一個二進制位,二進制位位1時,代表該列的值位null.

    • 記錄頭信息
      記錄頭信息用於描述記錄,由固定的5個字節組成,即40個二進制位,不同的位代表不同的意思:
      在這裏插入圖片描述

Dynamic和Compressed

Dynamic和Compressed類似於行格式, 只是處理行溢出不同,他們不會在記錄的真實數據處存儲一部分數據,而是把所有的數據都存儲到其他頁面,只有在記錄的真實數據處存儲其他頁面的地址.

Compressed行格式會採用壓縮算法對頁面進行壓縮.

索引

B+ 樹

我們把數據按下面的格式存,每個頁面都按照索引列的值建立了頁目錄.
在這裏插入圖片描述
其實就是B+樹:
在這裏插入圖片描述


上面的是模擬,InnoDB的做法:
當第一頁滿了以後,會把第一頁複製一份,把原來的第一頁作爲頁目錄.
這樣可以保證入口永遠不變.
在這裏插入圖片描述


葉子結點存了所有排好序的數據

聚集索引和輔助索引

  • 聚集索引

    • 按照每個表的主鍵構造一顆B+樹,同時頁節點存放的是整張表的行記錄數據,每一個葉子節點都被稱爲數據頁。
    • 聚集索引是邏輯上連續不是物理連續
    • 聚集索引對於主鍵的排序查找和範圍查找速度非常快
  • 輔助索引

    • 葉子節點並不包含記錄的全部數據,每個葉子節點中的索引行中存的不是這一行數據而是主鍵.
      通過這個主鍵去找對應的行數據

建立索引

建立索引 其實就是選擇要排序的鍵, 按照我們選的鍵 進行排序 建立新的B+樹

意思是用b c d 三個列 來建立索引, 就是b的值相同 就比較c 再比較d

create index idx_t1_bcd on t1(b,c,d)

索引的代價

空間上的代價

一個索引都爲對應一棵B+樹,樹中每一個節點都是一個數據頁,一個頁默認會佔用16KB的存儲空間,所以一個索引也是會佔用磁盤空間的。

時間上的代價

每次對錶中的數據進行增刪改操作時,都要去修改各個B+樹索引


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章