成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

InnoDB 行超長時怎么選擇溢出字段?

數據庫 MySQL
InnoDB 索引頁的大小默認為 16K,然而,varchar、text、blob 類型的單個字段內容長度就有可能超過 16K,這種情況下,整個索引頁都存不下一個字段的內容了。接下來,我們來聊聊 InnoDB 選擇溢出字段的邏輯。

InnoDB 索引頁的大小默認為 16K,然而,varchar、text、blob 類型的單個字段內容長度就有可能超過 16K,這種情況下,整個索引頁都存不下一個字段的內容了。

解決這個問題的辦法,是找到那些內容比較長的字段作為??溢出字段??,把它們的內容存放到溢出頁中,減少留在索引頁記錄中的內容。

接下來,我們來聊聊 InnoDB 選擇溢出字段的邏輯。

本文內容基于 MySQL 8.0.29 源碼。

正文

進入正題之前,大家可以思考一個問題:一個表中每條記錄的溢出字段都是一樣的嗎?

1、建表時的限制

單從字段數量看,MySQL 的 server 層限制一個表最多只能創建 1024 個字段。

InnoDB 則限制最多只能創建 1023 個字段,但是,如果我們創建表時,真要創建 1023 個字段,會很榮幸的收到這個錯誤:1117 - Too many columns。

因為 InnoDB 會往表中增加 2 ~ 3 個隱藏字段:DB_ROW_ID、DB_TRX_ID、DB_ROLL_PTR。

只有表中沒有主鍵,并且在建表時也沒有創建所有字段都不允許為 NULL? 的唯一索引時,才會增加 DB_ROW_ID 字段。

創建表時,能定義 1023 - 3 = 1020 個字段嗎?

依然不能,因為崩潰恢復過程中,解析 Redo 日志時,REDUNDANT? 記錄還會往表的內存對象(dict_table_t)中加入 3 個字段。

從以上介紹可知,InnoDB 需要保留 6 個字段自用,所以,我們建表時,最多能創建的字段數量是:1023 - 3 * 2 = 1017。

表中實際能創建多少個字段,除了受限于 server 層和存儲引擎的字段數量限制,還會受到字段長度的限制。

創建表時,InnoDB 會問自己一個問題:

如果我放過這條 DDL 語句,讓它建表成功,以后對這個表進行插入、更新操作時,有沒有可能因為記錄超長導致操作失敗?

要回答這個問題,總不能憑空想象,隨心而動吧?

所以,得有一個規則,要按規則辦事,規則是這樣的:

假定有資格被選擇成為溢出字段的那些字段,都已經被當作溢出字段了,它們的字段內容都部分或全部存放到溢出頁中了。

溢出字段內容是部分還是全部存放到溢出頁,這取決于記錄的格式。

REDUNDANT、COMPACT 記錄只會把溢出字段的部分內容存放到溢出頁。

DYNAMIC、COMPRESSED 記錄會把溢出字段的全部內容存放到溢出頁。

在這個規則之下,再來計算留在索引頁中的記錄內容長度,看看是不是還會超長?

如果還會超長,InnoDB 是不會放過這條 DDL 語句的,這時,建表就會失敗,并且報如下錯誤:

1118 - Row size too large (> 8126).
Changing some columns to TEXT or BLOB may help.
In current row format, BLOB prefix of 0 bytes is stored inline.

為啥判斷超長的條件是大于 8126 字節呢?先別急,后面會有介紹。

如果不會超長,自然就會建表成功了。

2、索引頁長什么樣?

InnoDB 的索引頁,不管是 B+ 樹的非葉子結點,還是葉子結點,初始化完成之后,未插入記錄之前,都包含以下幾個部分:

  • 38 字節的 File Header
  • 56 字節的索引頁頭信息
  • 13 字節的 Infimum 記錄
  • 13 字節的 Supremum 記錄
  • 2 字節的 Supremum Slot
  • 2 字節的 Infimum Slot
  • 8 字節的 File Trailer

總共占用 132 字節,如下圖所示:

圖片

3、怎么判斷行超長了?

通過上一小節,我們知道一個索引頁初始化完成之后,會占用 132 字節的空間。

索引頁默認大小為 16K,初始化之后,索引頁中剩余空間為:16 * 1024 - 132 = 16252 字節。

InnoDB 規定?:一個索引頁中最少要存放 2? 條記錄。所以,索引頁中一條記錄的最大長度就是:16252 / 2 = 8126 字節。

插入或者更新記錄時,如果插入記錄的長度,或者更新之后記錄的長度大于 8126 字節,就會選擇記錄中的部分字段作為溢出字段。

一條記錄的長度為下幾個部分的長度之和:

  • 字段 NULL 標記區域?,標記每個字段內容是否為 NULL,如果表中所有字段都定義為NOT NULL?,記錄中沒有此區域。
  • 字段內容長度區域?,存儲每個變長?字段的內容長度,如果表中所有字段都不是?變長字段,記錄中沒有此區域。
  • 記錄的頭信息,REDUNDANT 格式:6 字節;COMPACT、DYNAMIC、COMPRESSED 格式:5 字節。
  • 用戶字段內容。
  • DB_ROW_ID?,6 字節,創建表時,表中既沒有主鍵,也沒有創建所有字段都定義為 NOT NULL 的唯一索引時,InnoDB 才會添加這個列,作為表的主鍵。
  • DB_TRX_ID,8 字節,最后修改記錄的事務 ID。
  • DB_ROLL_PTR,7 字節,指向上一個事務產生的 undo 日志。

4、選擇溢出字段的邏輯

選擇溢出字段環節可能會進行一輪或多輪循環,每輪循環從表中選擇一個?字段作為溢出字段,直到留在索引頁中的記錄長度小于等于 8126 字節,選擇溢出字段環節也就結束了。

選擇溢出字段時,有一些字段是會被排除在外的,命中?以下規則的字段都不會被選為溢出字段:

  • 主鍵字段。
  • 固定長度字段(char、binary 字段除外)。
  • 內容為 NULL 的字段。
  • REDUNDANT、COMPACT 記錄,字段內容長度<= 788 字節。
  • DYNAMIC、COMPRESSED 記錄,字段內容長度<= 40 字節?,且字段類型是 BLOB、GEOMETRY、VAR_POINT。
  • DYNAMIC、COMPRESSED 記錄,字段內容長度<= 255 字節?,且字段類型不是 BLOB、GEOMETRY、VAR_POINT。

沒有命中以上規則的字段,都有資格被選為溢出字段。

每輪循環都會遍歷表中的所有字段,并根據以上規則,從有資格被選為溢出字段的那些字段中,找到??內容最長??的字段,就是溢出字段了。

5、頁地址

字段被選為溢出字段之后,該字段的部分或全部內容會存放到溢出頁,然后,索引頁記錄中,該字段的末尾?,會有一個 20 字節?的區域,保存著溢出頁地址。

20 字節的溢出頁地址由以下 4 個部分構成:

  • 表空間 ID,4 字節,溢出頁所在表空間 ID。
  • 頁號,4 字節,第 1 個溢出頁的頁號。一個溢出頁存不下字段的溢出內容時,會有多個溢出頁,組成溢出頁鏈表。
  • 字段內容 Offset?,4 字節,第 1 個溢出頁中,字段內容在頁中的 Offset。根據是否啟用了壓縮頁,字段內容在溢出頁中的 Offset 會不一樣,所以需要記下來。
  • 溢出頁內容長度?,當前字段存放到溢出頁中的內容長度,8 字節,實際只使用了最后4 字節來存儲溢出頁的內容長度之和,如下圖所示:

圖片

溢出字段留在索引頁記錄中的內容根據記錄格式的不同而不同:

REDUNDANT、COMPACT 記錄?,溢出字段在索引頁記錄中的長度為 788 字節,由以下兩部分組成:

  • 768 字節的字段內容。
  • 20 字節的溢出頁地址。

溢出字段中 768 字節之后的內容,會存放到溢出頁中。

DYNAMIC、COMPRESSED 記錄,溢出字段的全部內容都會存放到溢出頁中,索引頁記錄中只保存 20 字節的溢出頁地址。

6、回答文章開頭的問題

經過前面的介紹,相信大家對于本文開頭的那個問題已經有了答案,回到問題:

問:一個表中每條記錄的溢出字段都是一樣的嗎?

答?:每條記錄的溢出字段,可能一樣,也可能不一樣,記錄中哪些字段會成為溢出字段,取決于每條記錄中,所有有資格被選為溢出字段的內容長度。

7、總結

一條記錄中,所有字段內容長度之和超過 8126 字節時,就會有部分字段被選擇成為溢出字段。

選擇溢出字段可能會進行多輪循環?,每輪循環都會從有資格被選為溢出字段的那些字段中,選擇內容最長?的字段作為溢出字段,直到留在索引頁中的記錄長度小于等于 8126 字節。

REDUNDANT、COMPACT 記錄,溢出字段內容的前 768 字節存放在索引頁記錄中,剩余內容存放到溢出頁。

DYNAMIC、COMPRESSED 記錄,溢出字段的全部內容都存放到溢出頁。

本文轉載自微信公眾號「一樹一溪」,可以通過以下二維碼關注。轉載本文請聯系一樹一溪公眾號。

責任編輯:姜華 來源: 一樹一溪
相關推薦

2021-12-15 19:37:49

索引字符串字段

2023-12-07 07:22:52

MySQLIGNORE

2009-05-05 10:19:37

存儲引擎InnoDBMyISAM

2011-09-14 17:18:04

方正筆記本

2011-09-20 17:29:56

筆記本技巧

2009-05-19 09:58:41

MyISAMInnoDB存儲引擎

2023-09-04 09:42:43

2020-05-09 13:49:00

內存空間垃圾

2022-11-17 09:14:58

MySQL加行級鎖幻讀

2024-04-15 10:30:22

MySQL存儲引擎

2010-12-16 09:34:48

差異備份

2022-07-13 07:31:43

數據分片SQL

2022-08-04 10:18:32

棧遷移?寄存器內存

2021-07-28 10:35:14

云計算云計算環境云區域

2018-08-26 06:24:58

MySQLInnoDB行鎖

2009-07-27 16:22:54

GridView選擇行

2022-06-30 08:01:53

mysqlmyisamcount

2011-07-22 09:54:37

屏蔽布線系統

2012-04-01 09:43:24

摩托羅拉

2013-01-17 09:49:51

BI企業云數據分析
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产二区视频 | 国产精品一级在线观看 | 中文字幕在线视频免费观看 | 久久久久免费 | 伊人精品一区二区三区 | www久久国产 | 日韩福利在线 | 中文字幕av网站 | 久久精品一区二区三区四区 | 日本不卡一区 | 亚洲444kkkk在线观看最新 | 欧美日韩黄 | 国产成人99久久亚洲综合精品 | 亚洲自拍偷拍av | av成年人网站 | 国产东北一级毛片 | 天堂资源最新在线 | 在线视频国产一区 | 成人在线精品 | 日韩一区二区在线播放 | 国产一区二区不卡 | 精品美女在线观看 | 国产精品久久久久无码av | 欧美日韩国产一区二区 | 午夜精品在线观看 | 隔壁老王国产在线精品 | 日韩人体在线 | 天天草天天干 | 日韩在线观看视频一区 | 超碰日本 | 国产精品美女久久久久久不卡 | 国产欧美日韩一区 | 波多野结衣中文字幕一区二区三区 | 成人在线免费视频 | 国产免费一区 | 国产综合精品一区二区三区 | 精品成人佐山爱一区二区 | 日韩高清国产一区在线 | 91视频播放 | 在线欧美日韩 | 成人福利网 |