天天看點

mysql中資料頁的相關概念

概念

在 InnoDB 存儲引擎中,所有的資料都被邏輯地存放在表空間中,表空間(tablespace)是存儲引擎中最高的存儲邏輯機關,在表空間的下面又包括段(segment)、區(extent)、頁(page),他們之間的關系如下:

mysql中資料頁的相關概念

資料頁

頁是mysql中磁盤和記憶體交換的基本機關,也是mysql管理存儲空間的基本機關。

同一個資料庫執行個體的所有表空間都有相同的頁大小;預設情況下,表空間中的頁大小都為 16KB,當然也可以通過改變 innodb_page_size 選項對預設大小進行修改,需要注意的是不同的頁大小最終也會導緻區大小的不同。

一次最少從磁盤讀取16KB内容到記憶體中,一次最少把記憶體中16KB内容重新整理到磁盤中,當然了單頁讀取代價也是蠻高的,一般都會進行預讀

mysql中資料頁的相關概念
名稱 中文名 占用空間大小 簡單描述

​File Header​

檔案頭部 38位元組 頁的一些通用資訊

​Page Header​

頁面頭部 56位元組 資料頁專有的一些資訊

​Infimum​

​​ + ​

​Supremum​

最小記錄和最大記錄 26位元組 兩個虛拟的行記錄

​User Records​

使用者記錄 不确定 實際存儲的行記錄内容

​Free Space​

空閑空間 不确定 頁中尚未使用的空間

​Page Directory​

頁面目錄 不确定 頁中的某些記錄的相對位置

​File Trailer​

檔案尾部 8位元組 校驗頁是否完整

Infimum + Supremum

  • 這個值位于整個頁面的第三部分
  • 分别是最小記錄和最大記錄,屬于MySQL為每個頁添加的​

    ​虛拟記錄​

  • 由五個位元組的​

    ​記錄頭​

    ​ 和 八個位元組的 值(分别是單詞​

    ​Infimum​

    ​和​

    ​Supremum​

    ​)組成
  • 最小記錄的記錄頭中​

    ​heap_no​

    ​為0
  • 最大記錄的記錄頭中​

    ​heap_no​

    ​為1
  • 也就是說正式記錄中的​

    ​heap_no​

    ​屬性從2開始
  • 最小記錄的record_type 是2
  • 最大記錄的record_type 是3
  • 最小記錄是頁中單連結清單的頭結點
  • 最大記錄是頁中單連結清單的尾結點

​Page Directory​

  • 這個頁目錄裡面存的是一個一個的槽(​

    ​slot​

    ​)
  • 每個槽指向組内最大記錄的位址偏移量(我了解為頁内偏移量)
  • 這個資料結構是數組,按主鍵值從小到大排列
  • 這種結構注定了查詢最快的方式是二分法,時間複雜度O(lgN)
  • ​頁分裂​

    ​(前面說過) 時會增加一個槽

​User Records​

​​ 和 ​

​Free Space​

  • 完全空閑的頁是沒有 ​

    ​User Records​

    ​部分的
  • 插入資料時,從​

    ​Free Space​

    ​配置設定空間給​

    ​User Records​

    ​,直到​

    ​Free Space​

    ​沒有空間或空間不夠配置設定新的記錄,這時需要申請新的頁

​Page Header​

名稱 占用空間大小 描述

​PAGE_N_DIR_SLOTS​

2位元組 在頁目錄中的槽數量

​PAGE_HEAP_TOP​

2位元組 還未使用的空間最小位址,也就是說從該位址之後就是Free Space

​PAGE_N_HEAP​

2位元組 本頁中的記錄的數量(包括最小和最大記錄以及标記為删除的記錄)

​PAGE_FREE​

2位元組 第一個已經标記為删除的記錄位址(各個已删除的記錄通過next_record也會組成一個單連結清單,這個單連結清單中的記錄可以被重新利用)

​PAGE_GARBAGE​

2位元組 已删除記錄占用的位元組數

​PAGE_LAST_INSERT​

2位元組 最後插入記錄的位置

​PAGE_DIRECTION​

2位元組 記錄插入的方向

​PAGE_N_DIRECTION​

2位元組 一個方向連續插入的記錄數量

​PAGE_N_RECS​

2位元組 該頁中記錄的數量(不包括最小和最大記錄以及被标記為删除的記錄)

​PAGE_MAX_TRX_ID​

8位元組 修改目前頁的最大事務ID,該值僅在二級索引中定義

​PAGE_LEVEL​

2位元組 目前頁在B+樹中所處的層級

​PAGE_INDEX_ID​

8位元組 索引ID,表示目前頁屬于哪個索引

​PAGE_BTR_SEG_LEAF​

10位元組 B+樹葉子段的頭部資訊,僅在B+樹的Root頁定義

​PAGE_BTR_SEG_TOP​

10位元組 B+樹非葉子段的頭部資訊,僅在B+樹的Root頁定義

1.​

​PAGE_GARBAGE​

  • 在頁面空間不夠時,會嘗試将所需空間與這個值比較,如果夠,那麼将記錄移到臨時表中,再重新插回來(記錄逐條新增是不會産生碎片空間的),但很明顯,這很耗性能
  1. ​PAGE_BTR_SEG_LEAF​

    ​​ 和 ​

    ​PAGE_BTR_SEG_TOP​

  • 後面會說到段的概念,一個索引會有兩個段,一個葉子節點段,一個非葉子節點段,這兩個屬性分别代表一個 ​

    ​Segment Header​

    ​,代表了哪個表空間哪個頁面的哪個​

    ​INODE Entry​

    ​ (表空間号 + 頁面号 + 偏移量值)

​File Header​

名稱 占用空間大小 描述

​FIL_PAGE_SPACE_OR_CHKSUM​

4位元組 頁的校驗和(checksum值)

​FIL_PAGE_OFFSET​

4位元組 頁号

​FIL_PAGE_PREV​

4位元組 上一個頁的頁号

​FIL_PAGE_NEXT​

4位元組 下一個頁的頁号

​FIL_PAGE_LSN​

8位元組 頁面被最後修改時對應的日志序列位置(英文名是:Log Sequence Number)

​FIL_PAGE_TYPE​

2位元組 該頁的類型

​FIL_PAGE_FILE_FLUSH_LSN​

8位元組 僅在系統表空間的一個頁中定義,代表檔案至少被重新整理到了對應的LSN值

​FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID​

4位元組 頁屬于哪個表空間

這個屬性裡面的值就說三個:

  • ​FIL_PAGE_OFFSET​

  1. 每個表空間的頁号唯一,四個位元組足夠用了
  • ​FIL_PAGE_PREV​

    ​​ 和 ​

    ​FIL_PAGE_NEXT​

  1. 上一頁和下一頁,诶喲,這不是雙向連結清單啊,那所有的頁加起來組成了一個雙向連結清單哇,好玩吧~
  • ​FIL_PAGE_TYPE​

類型名稱 十六進制 描述

​FIL_PAGE_TYPE_ALLOCATED​

0x0000 最新配置設定,還沒使用

​FIL_PAGE_UNDO_LOG​

0x0002 Undo日志頁

​FIL_PAGE_INODE​

0x0003 段資訊節點

​FIL_PAGE_IBUF_FREE_LIST​

0x0004 Insert Buffer空閑清單

​FIL_PAGE_IBUF_BITMAP​

0x0005 Insert Buffer位圖

​FIL_PAGE_TYPE_SYS​

0x0006 系統頁

​FIL_PAGE_TYPE_TRX_SYS​

0x0007 事務系統資料

​FIL_PAGE_TYPE_FSP_HDR​

0x0008 表空間頭部資訊

​FIL_PAGE_TYPE_XDES​

0x0009 擴充描述頁

​FIL_PAGE_TYPE_BLOB​

0x000A BLOB頁

​FIL_PAGE_INDEX​

0x45BF
  • 假設一條查詢語句定位到了這個頁面
  • 先将條件中的列(加深為​

    ​col​

    ​)與值(假設為​

    ​x​

    ​)拎出來,二分法定位在哪個組。
  1. 假設10個槽,(0 + 9)/2 = 4, 将第四個槽的條件列的值拿出來跟​

    ​x​

    ​比較,如果​

    ​x​

    ​大,那就從5~9的槽中繼續二分找;如果​

    ​x​

    ​小, 那就從0~4的槽中繼續二分;
  2. 直到前後兩個槽相差為1,那記錄就在那個大的槽裡面,又每個槽其實存的是組内最大記錄,那前一個槽對應記錄的下一個節點就是目标槽對應組中的最小值,順着單連結清單往後一個一個比就完事了,每組最多八條記錄,這速度還是很快的。