MySQL:一行記錄如何

1、表空間文件結構

表空間由段「segment」、區「extent」、頁「page」、行「row」組成,InnoDB存儲引擎的邏輯存儲結構大致如下圖:

數據庫表中的記錄都是按「行」進行存放的,每行記錄根據不同的行格式,有不同的存儲結構。

記錄是按照行來存儲的,但是數據庫的讀取并不以「行」為單位,否則一次讀取(也就是一次 I/O 操作)只能處理一行數據,效率會非常低。

因此,InnoDB 的數據是按「頁」為單位來讀寫的,也就是說,當需要讀一條記錄的時候,并不是將這個行記錄從磁盤讀出來,而是以頁為單位,將其整體讀入內存。

默認每個頁的大小為 16KB,也就是最多能保證 16KB 的連續存儲空間。

頁是 InnoDB 存儲引擎磁盤管理的最小單元,意味著數據庫每次讀寫都是以 16KB 為單位的,一次最少從磁盤中讀取 16KB 的內容到內存中,一次最少把內存中的 16KB 內容刷新到磁盤中。

B+ 樹中每一層都是通過雙向鏈表連接起來的,如果是以頁為單位來分配存儲空間,那么鏈表中相鄰的兩個頁之間的物理位置并不是連續的,可能離得非常遠,那么磁盤查詢時就會有大量的隨機 I/O,隨機 I/O 是非常慢的。

怎么解決呢?

在表中數據量大的時候,為某個索引分配空間的時候就不再按照頁為單位分配了,而是按照「區」為單位分配。每個區的大小為 1MB,對于 16KB 的頁來說,連續的 64 個頁會被劃為一個區,這樣就使得鏈表中相鄰的頁的物理位置也相鄰,就能使用順序 I/O 了。

表空間是由各個段組成的,段是由多個區組成的。段一般分為「數據段」、「索引段」和「回滾段」等。

  • 索引段:存放 B + 樹的非葉子節點的區的集合。
  • 數據段:存放 B + 樹的葉子節點的區的集合。
  • 回滾段:存放的是回滾數據的區的集合,MVCC 利用了回滾段實現了多版本查詢數據。

2、InnoDB 行格式

有下面 4 種行格式:

  • Redundant:MySQL 5.0 版本之前用的行格式,不緊湊。
  • Compact:MySQL 5.1 版本之后,行格式默認設置成 Compact。一種緊湊的行格式,可以讓一頁存儲更多行記錄。
  • DynamicCompressed:從 MySQL5.7 版本之后,默認使用 Dynamic 行格式。 兩個都是緊湊的行格式,它們的行格式都和 Compact 差不多,都是基于 Compact 改進一點東西。

COMPACT 行格式

記錄的額外信息
1. 變長字段長度列表

varchar(n)char(n) 的區別:char 是定長的,varchar 是變長的,變長字段實際存儲的數據的長度(大小)不固定的。

在存儲數據的時候,要把數據占用的大小存起來,存到「變長字段長度列表」里面,讀取數據的時候才能根據這個「變長字段長度列表」去讀取對應長度的數據。其他 TEXT、BLOB 等變長字段也是這么實現的。

【示例】創建下面表進行演示:

假設有下面三條記錄:

image.png

第一條記錄「只看變長字段」:

  • name字段值為 a,占 1 字節。
  • phone 字段值為 123,占 3 字節。

這些變長字段的真實數據占用的字節數會按照列的順序 逆序存放,所以「變長字段長度列表」里的內容是「 03 01」,而不是 「01 03」。

同理,第二條記錄:

第三條記錄phone 列的值是 NULL,NULL 是不會存放在行格式中記錄的真實數據部分里的,所以「變長字段長度列表」里不需要保存值為 NULL 的變長字段的長度。

【為什么「變長字段長度列表」的信息要按照逆序存放】

因為「記錄頭信息」中指向下一個記錄的指針,指向的是下一條記錄的「記錄頭信息」和「真實數據」之間的位置,這樣的好處是向左讀就是記錄頭信息,向右讀就是真實數據,比較方便。

「變長字段長度列表」中的信息之所以要逆序存放,是因為這樣可以使得位置靠前的記錄的真實數據和數據對應的字段長度信息可以同時在一個 CPU Cache Line 中,這樣就可以提高 CPU Cache 的命中率

當數據表沒有變長字段的時候,比如全部都是 int 類型的字段,這時候表里的行格式就不會有「變長字段長度列表」了,因為沒必要,不如去掉以節省空間。

所以「變長字段長度列表」只出現在數據表有變長字段的時候。

2. NULL 值列表

表中的某些列可能會存儲 NULL 值,如果把這些 NULL 值都放到記錄的真實數據中會比較浪費空間,所以 Compact 行格式把這些值為 NULL 的列存儲到 NULL 值列表中。

如果存在允許 NULL 值的列,則每個列對應一個二進制位(bit),二進制位按照列的順序逆序排列。

  • 二進制位的值為1時,代表該列的值為 NULL。
  • 二進制位的值為0時,代表該列的值不為 NULL。

另外,NULL 值列表必須用整數個字節的位表示(1字節8位),如果使用的二進制位個數不足整數個字節,則在字節的高位補 0

當一條記錄有 9 個字段值都是 NULL,那么就會創建 2 字節空間的「NULL 值列表」,以此類推。

當數據表的字段都定義成 NOT NULL 的時候,這時候表里的行格式就不會有 NULL 值列表了

所以在設計數據庫表的時候,通常都是建議將字段設置為 NOT NULL,這樣可以至少節省 1 字節的空間(NULL 值列表至少占用 1 字節空間)。


【舉例】以上面表舉例:

第一條記錄:

但是 InnoDB 是用整數字節的二進制位來表示 NULL 值列表的,現在不足 8 位,所以要在高位補 0,最終用二進制來表示:

第二條記錄:

第三條記錄 phone 列 和 age 列是 NULL 值,所以,對于第三條數據,NULL 值列表用十六進制表示是 0x06。

?NULL 值列表填充完畢后,行格式為下面這樣:

3. 記錄頭信息

列舉比較重要的幾個:

  • delete_mask:標識此條數據是否被刪除。執行 detele 刪除記錄的時候,并不會真正的刪除記錄,只是將這個記錄的 「delete_mask」標記為 1
  • next_record:下一條記錄的位置。記錄與記錄之間是通過鏈表組織的,指向的是下一條記錄的「記錄頭信息」和「真實數據」之間的位置,這樣的好處是向左讀就是記錄頭信息,向右讀就是真實數據,比較方便。
  • record_type:表示當前記錄的類型,0 表示普通記錄,1 表示 B+ 樹非葉子節點記錄,2 表示最小記錄,3 表示最大記錄。
記錄的真實數據

記錄真實數據部分除了自定義的字段,還有三個隱藏字段,分別為:row_idtrx_idroll_pointer

  • row_id:建表的時候指定了主鍵或者唯一約束列,那么就沒有 row_id 隱藏字段了。如果既沒有指定主鍵,又沒有唯一約束,那么 InnoDB 就會為記錄添加 row_id 隱藏字段。row_id 不是必需的,占用 6 個字節。

  • trx_id:事務id,表示這個數據是由哪個事務生成的。 trx_id 是必需的,占用 6 個字節。

  • roll_pointer:這條記錄上一個版本的指針。roll_pointer 是必需的,占用 7 個字節。

MVCC 機制就跟 trx_id 和 roll_pointer 的作用有關。

varchar(n) 中的 n 最大取值

MySQL 規定除了 TEXT、BLOBs 這種大對象類型之外,其他所有的列(不包括隱藏列和記錄頭信息)占用的字節長度「加起來」不能超過 65535 個字節

varchar(n) 字段類型的 n 代表的是最多存儲的字符數量,并不是字節大小。

要算 varchar(n) 最大能允許存儲的字節數,還要看數據庫表的字符集,因為字符集代表著:1個字符要占用多少字節,比如 ascii 字符集, 1 個字符占用 1 字節,那么 varchar(100) 意味著最大能允許存儲 100 字節的數據。

【單字段情況】

在算 varchar(n) 中 n 最大值時,需要減去 「變長字段長度列表」和 「NULL 值列表」所占用的字節數的。

【多字段情況】

如果有多個字段的話,要保證「所有字段的長度 + 變長字段字節數列表所占用的字節數 + NULL值列表所占用的字節數」 <= 65535。

行溢出后,如何存儲數據

如果一個數據頁存不了一條記錄,InnoDB 存儲引擎會自動將溢出的數據存放到「溢出頁」中。

在記錄的真實數據處只會保存該列的一部分數據,而把剩余的數據放在「溢出頁」中,然后「真實數據」處用 20 字節存儲指向溢出頁的地址,從而可以找到剩余數據所在的頁。

?轉載:MySQL 一行記錄是怎么存儲的? | 小林coding (xiaolincoding.com)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/713769.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/713769.shtml
英文地址,請注明出處:http://en.pswp.cn/news/713769.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

hippy 調試demo運行聯調-mac環境準備篇

適用對于終端編譯環境不熟悉的人看&#xff0c;僅mac端 hippy 調試文檔官網地址 前提&#xff1a;請使用node16 聯調預覽效果圖&#xff1a; 編譯iOS Demo環境準備 未跑通&#xff0c;待補充 編譯Android Demo環境準備 1、正常安裝Android Studio 2、下載Android NDK&a…

Windows系統誤刪文件恢復

最近很多用戶反饋誤刪文件的場景比較多.下面華仔將講解數據恢復的原理和過程.以及一些注意事項。 建議的數據恢復軟件 1.EaseUS Data Recovery Wizard(易我數據恢復)需要斷網使用 2.Wondershare Recoverit(萬興數據恢復)&#xff0c; Windows系統刪除文件原理&#xff1a;如果是…

Android ShellUtils手機管理器

1. Android ShellUtils手機管理器 Android Shell工具類&#xff0c;可用于檢查系統root權限&#xff0c;并在shell或root用戶下執行shell命令。如&#xff1a; checkRootPermission() 檢查root權限 。execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg)…

HTTPS是什么,詳解它的加密過程

目錄 1.前言 2.兩種加密解密方式 2.1對稱加密 2.2非對稱加密 3.HTTPS的加密過程 3.1針對明文的對稱加密 3.2針對密鑰的非對稱加密 3.3證書的作用 1.前言 我們知道HTTP協議是超文本傳輸協議,它被廣泛的應用在客戶端服務器上,用來傳輸文字,圖片,視頻,js,html等.但是這種傳…

java數據結構與算法刷題-----LeetCode572. 另一棵樹的子樹(經典題,樹字符串化KMP)

java數據結構與算法刷題目錄&#xff08;劍指Offer、LeetCode、ACM&#xff09;-----主目錄-----持續更新(進不去說明我沒寫完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目錄 1. 暴力求解&#xff0c;深度優先2. KMP算法進行串匹配 1. 暴力求…

WinForm、Wpf自動升級 AutoUpdater.NET

Github AutoUpdater.NET 目錄 一、IIS部署 更新站點 二、創建Winform 一、IIS部署 更新站點 IIS默認站點目錄下創建 目錄 Downloads、Updates Updates目錄創建文件 UpdateLog.html、AutoUpdaterStarter.xml UpdateLog.html&#xff1a; <html><body><h1…

從零開始手寫RPC框架(2)——Netty入門

學習前需要掌握基本的java網絡編程&#xff0c;可參考這篇博客 目錄 Netty 簡介Netty 使用 kryo 序列化傳輸對象案例客戶端代碼服務端代碼編碼器 Netty 簡介 是什么&#xff1f; Netty 是一個基于 NIO (Non-blocking I/O&#xff0c;非阻塞I/O)的 client-server(客戶端服務器…

mysql學習--binlog與gtid主從同步

基礎環境 基于centOS7-MySQL8.0.35版本 我們先準備一臺主服務器兩臺從服務器來實現我們主從同步的訴求 Master&#xff1a;192.168.75.142 slave1:192.168.75.143 slave&#xff1a;192.168.75.145 binlog主從同步 主庫配置 #我們需要在主從庫中都需要添加server_id&am…

大龍談智能內容開通視頻號啦

大家好&#xff0c;大龍談只能內容開通視頻號了&#xff0c;歡迎大家掃碼關注&#xff1a;

RISC-V特權架構 - 中斷與異常概述

RISC-V特權架構 - 中斷與異常概述 1 中斷概述2 異常概述3 廣義上的異常3.1 同步異常3.2 異步異常3.3 常見同步異常和異步異常 本文屬于《 RISC-V指令集基礎系列教程》之一&#xff0c;歡迎查看其它文章。 1 中斷概述 中斷&#xff08;Interrupt&#xff09;機制&#xff0c;即…

RocketMQ安裝

mq服務端安裝配置啟動把windows做成服務 mq管理界面安裝配置啟動 mq服務端 安裝 RocketMQ下載地址 配置 ROCKETMQ_HOME D:\google-d\rocketmq-all-5.2.0-bin-release啟動 # bin目錄cmd輸入 start mqnamesrv.cmd把windows做成服務 http://t.csdnimg.cn/qd2RD mq管理界面 …

ubuntu22.04安裝mysql8.0

官網下載mysql&#xff1a;MySQL :: Download MySQL Community Server 將mysql-server_8.0.20-2ubuntu20.04_amd64.deb-bundle.tar上傳到/usr/local/src #解壓壓縮文件 tar -xvf mysql-server_8.0.20-2ubuntu20.04_amd64.deb-bundle.tar解壓依賴包依次輸入命令 sudo dpkg -i m…

編程筆記 Golang基礎 045 math包

編程筆記 Golang基礎 045 math包 一、math包主要功能常量&#xff1a;函數&#xff1a;數值運算&#xff1a;三角函數&#xff1a;對數函數&#xff1a;隨機數相關&#xff1a; 二、示例代碼一三、示例代碼二小結 Go 語言的標準庫 math 提供了一系列基礎數學函數和常量&#xf…

EasyRecovery數據恢復軟件2024最新版包括Windows和Mac

EasyRecovery數據恢復軟件適用于多種環境和使用場景。首先&#xff0c;它適用于各種操作系統&#xff0c;包括Windows和Mac。無論用戶使用的是哪種操作系統&#xff0c;都可以使用該軟件進行數據恢復。 其次&#xff0c;EasyRecovery支持從各種存儲設備和媒介中恢復數據&#…

自定義BeanNameGenerator生成規則

通過點進ComponentScan注解進入源碼可以看到 追隨BeanNameGenerator進入源碼可以看到該類是個借口且只有一個方法 點擊上面黑色箭頭出現兩個實現方法 點擊第一個方法 進入determineBeanNameFromAnnotation方法中 通過上訴自定義一個生成beanName方法 先創建一個CustomeBeanN…

使用結構體和類在Unity中管理IMU數據

使用結構體和類在Unity中管理IMU數據 IMU數據簡介使用結構體管理IMU數據結構體的優點結構體的使用場景 使用類管理IMU數據類的優點類的使用場景 結構體(struct) vs 類(class)為什么考慮使用結構體 結論 在Unity開發中&#xff0c;合理地選擇數據結構對于確保游戲和應用的性能和…

60 個 CSS 選擇器,一網打盡!

CSS 選擇器用于選擇 HTML 元素并將樣式應用于它們。使用這些選擇器&#xff0c;可以定義特定條件下應用哪些樣式。除了普通的選擇器外&#xff0c;還有偽類和偽元素&#xff0c;用于選擇具有特定狀態或特定部分的元素&#xff0c;并將樣式應用于它們。本文將通過圖文并茂的方式…

Windows11家庭版安裝Docker

文章目錄 安裝Docker安裝hyper-v繼續解決報錯完成效果圖進一步測試是否完成安裝 安裝Docker windows如何安裝docker 裝好之后&#xff0c;我打開報錯。 安裝hyper-v 按這個視頻操作&#xff1a;Windows 11 家庭版安裝 Hyper-V bat文件里的代碼是&#xff1a; pushd "…

【Educoder數據挖掘實訓】異常值檢測-3σ法

【Educoder數據挖掘實訓】異常值檢測-3σ法 開挖&#xff01; 這個異常值檢測基于的是兩點&#xff1a; 數據往往遵循正態分布在正態分布中&#xff0c; [ μ ? 3 σ , μ 3 σ ] [\mu - 3\sigma, \mu 3\sigma] [μ?3σ,μ3σ]包含了正態分布中 99.74 % 99.74\% 99.74%的數…

【投稿優惠|快速見刊】2024年圖像,機器學習和人工智能國際會議(ICIMLAI 2024)

【投稿優惠|快速見刊】2024年圖像&#xff0c;機器學習和人工智能國際會議&#xff08;ICIMLAI 2024&#xff09; 重要信息 會議官網&#xff1a;http://www.icimlai.com會議地址&#xff1a;深圳召開日期&#xff1a;2024.03.30截稿日期&#xff1a;2024.03.20 &#xff08;先…