InnoDB存儲引擎(四)表

目錄

 

4.1 索引組織表

4.2 InnoDB邏輯存儲結構

4.2.1 表空間

4.2.2 段

4.2.3 區

4.2.4 頁

4.2.5 行

4.3 行記錄格式

4.3.1 Compact行記錄格式

4.3.2 行溢出數據

4.3.4 CHAR的行結果存儲

4.4 InnoDB數據頁結構

4.4.1 Infimum和Supremum Record

4.4.2 Page Directory


4.1 索引組織表

索引組織表:表都是根據主鍵順序組織存放的。

每張表都有一個主鍵,如果創建表時沒有顯式地定義主鍵,InnoDB首先會判斷是否有非空的唯一索引,有,則該列爲主鍵;否則自動創建一個6字節大小的指針_rowid。

4.2 InnoDB邏輯存儲結構

所有數據都被邏輯地存放在一個空間(tablespace)中,稱之爲表空間。表空間又由段(segment)、區(extent)、頁(page)組成。

邏輯存儲結構

4.2.1 表空間

所有數據都存放在表空間中,默認ibdata1,如果啓用innodb_file_per_table,則每個表內的數據可以單獨放到一個表空間(.ibd)內。

注意,如果啓用了innodb_file_per_table,每張表的表空間內存放的只是的數據、索引和插入緩衝BITMAP頁,其他類的信息,如回滾日誌、插入緩衝、索引頁、系統事務信息、二次緩衝寫等還是存放在原來的共享表空間內。

4.2.2 段

常見的段有數據段、索引段、回滾段等。

InnoDB存儲引擎表是索引組織的,因此數據即索引、索引即數據。數據段即爲B+樹的葉子節點,索引即爲B+樹的非索引節點。回滾段比較特殊,後面單獨介紹。

4.2.3 區

由連續頁組成的空間,在任何情況下每個區的大小都爲1MB。爲了保證區中頁的連續性,InnoDB 存儲引擎一次從磁盤申請4~5個區。在默認情況下,InnoDB存儲引擎頁的大小爲16KB,即一個區中一共有64個連續的頁。

啓用innodb_file_per_table後,先使用32個頁大小的碎片頁來存放數據,在使用完這些頁之後纔是64個連續頁的申請。目的:在開始時申請較小的空間,節約磁盤容量的開銷。

4.2.4 頁

磁盤管理的最小單位,默認16KB。

常見的頁類型有:

  ■ 數據頁

  ■ undo頁

  ■ 系統頁

  ■ 事務數據頁

  ■ 插入緩衝位圖頁

  ■ 插入緩存空閒列表頁

  ■ 未壓縮的二進制大對象頁

  ■ 壓縮的二進制大對象頁

4.2.5 行

InnoDB存儲引擎是面向行的,數據是按照行進行存放的。每個頁最多存放16KB/2-200=7992行記錄。

4.3 行記錄格式

通過SHOW TABLE STATUS like 'table_name'來查看當前表使用的行格式。

行記錄格式有:Compact、Redundant、Compress、Dynamic。

mysql> show table status like 'user'\G;
************************* 1. row ***************************
           Name: user
         Engine: InnoDB
        Version: 10
     Row_format: Compact
           Rows: 30
 Avg_row_length: 546
    Data_length: 16384
Max_data_length: 0
   Index_length: 16384
      Data_free: 0
 Auto_increment: 1037
    Create_time: 2019-09-11 04:27:05
    Update_time: NULL
     Check_time: NULL
      Collation: utf8_bin
       Checksum: NULL
 Create_options: row_format=COMPACT
        Comment: 
1 row in set (0.00 sec)

4.3.1 Compact行記錄格式

MySQL 5.0引入,設計目標是高效地存儲數據。一個頁存放的行數據越多,其性能就越1高。

Compact行記錄格式

1. 變成字段長度列表

非NULL,記錄字段的實際長度,按照列的順序逆序放置,若列的長度小於255字節,用1字節表示;若大於255個字節,用2字節表示。變成字段的長度最大不能超過2字節,因爲VARCHAR類型的最大長度限制爲65535。

2. NULL標誌位

標識行數據是否有NULL值,有則用1表示

3. 記錄頭信息

頭信息

4. 列數據

實際存儲每個列的數據。

注意:NULL不佔該部分任何空間,即NULL除了佔有NULL標誌位,實際存儲不佔用任何空間。

5. 隱藏列

事務ID列和回滾指針,如果沒有定義主鍵,每行還會增加一個6字節的rowid列。

案例:

1. 新建表並且向表中插入數據

2. 分析結果

4.3.2 行溢出數據

將一條記錄中的某些數據存儲在真正的數據頁面之外。

VARCHAR最多可以存儲65535字節,但是真的可以嗎?

mysql> create table test(
    -> a varchar(65535)
    -> )charset=latin1 engine=innodb;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

說明有其他開銷(主鍵、事務id、回滾指針),實際能存放65532。

如果設置字符類型爲UFT-8和GBK,結果如何?

行溢出數據的存儲,數據頁保存前768字節的前綴數據,之後是偏移量,指向行溢出頁。

InnoDB 1.0.x版本開始引入了新的文件格式:Compressed和Dynamic,採用完全的行溢出方式,在數據頁只存放20個字節的指針,實際存放的數據都在Off Page中。

4.3.4 CHAR的行結果存儲

在多字節多字符的情況下,CHAR和VARCHAR的實際行存儲基本是沒有區別的。

4.4 InnoDB數據頁結構

由七個部分組成,如下:

名稱

字節數 作用
File Header(文件頭) 38 記錄頁的一些頭信息
Page Header(頁頭) 56 記錄數據頁的狀態信息
Infimum和Supremum Record -- 虛擬的行記錄,用來限定記錄的邊界
User Record(用戶記錄,即行記錄) -- 實際存儲行記錄內容
Free Space(空閒空間) -- 一條記錄被刪除後,該空間會被加入到空閒列表中
Page Directory(頁目錄) -- 存放記錄的相對地址
File Trailer(文件結尾信息) 8 檢測頁是否已經完整地寫入磁盤

4.4.1 Infimum和Supremum Record

虛擬的行記錄,用來限定記錄的邊界。

Infimum記錄是比該頁中任何主鍵值都要小的值,Supremum指比任何可能大的值還要大的值。這兩個值在頁創建時被建立,並且在任何情況下不會被刪除。

4.4.2 Page Directory

存放記錄的相對位置(注意,這裏存放的是頁相對位置,而不是偏移量),有時候這些記錄指針稱爲Slots(槽)或者目錄槽(Directory Slots)。一個槽中可能有多個記錄。由於Page Directory是稀疏目錄,二叉查找的結果只是一個粗略的結果,因此必須通過record header中的next_record來繼續查找相關記錄。

如下圖,15,18組成一個槽,找到槽之後,還需要通過指針找到記錄。

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