InnoDB數據頁

導讀:

? 我們已經知道了頁是數據庫存儲的基本單位,知道了一條行記錄的存儲格式是怎樣的,當數據越來越多時,那一條條行記錄具體又是怎么在頁中被組織起來的呢?

一、InnoDB數據頁結構

二、總結

1、一條條行數據是如何在數據頁中被組織起來的?

? 首先,在每一個數據頁中存在兩個虛擬記錄,一個代表最小記錄,一個代表最大記錄,它們被存儲在數據頁的 Infimum + Supremum 部分。

? 緊接著,當向表中插入一些數據時,這些記錄會被存儲在數據頁中的 User Records 中,這里不僅存儲了其真實內容,還有存儲了一些額外的數據,比如頭信息中的 next_record,通過這個標記加上兩個虛擬記錄,使得記錄形成了一條按照主鍵值由小到大的順序的單鏈表(非插入順序)。

? 然后,為了數據能夠查的更快,將數據頁中的數據進行了分組,每組最后一個記錄的地址偏移量作為槽,存放在 Page Directory(頁目錄),這樣對于之后通過主鍵查詢記錄時,只需通過二分法確定目標結果存儲在哪個組,然后在組中通過記錄的 next_record 屬性進行遍歷即可找到目標。這樣就完成了一個數據頁中數據的組織。

? 最后,一個數據頁默認大小為 16 KB,當一個數據頁不足存儲新數據時,將會申請新的數據頁進行存儲。此時,數據頁結構中的 File Header 就發揮作用,其包含 FIL_PAGE_PREV 和 FIL_PAGE_NEXT 兩個屬性,它們分別代表本頁的上一個和下一個頁的頁號,這樣就可通過這兩個屬性將許許多多的頁就都串聯起來了,形成一個雙向鏈表。

? 總的來說,各個數據頁可以組成一個雙向鏈表,而每個數據頁中的記錄會按照主鍵值從小到大的順序組成一個單向鏈表,每個數據頁都會為存儲在它里邊兒的記錄生成一個頁目錄,在通過主鍵查找某條記錄的時候可以在頁目錄中使用二分法快速定位到對應的槽,然后再遍歷該槽對應分組中的記錄即可快速找到指定的記錄。

三、在 MySQL InnoDB 的頁目錄(Page Directory)設計中,為什么槽(Slot)記錄的是分組中??最大主鍵值??,而不是最小值?

? 在 InnoDB 數據頁中,所有記錄按主鍵順序物理存儲(升序排列)。頁目錄的槽將這些記錄分成多個分組(例如,每個分組通常包含 4-8 條記錄),槽的信息允許二分查找快速定位目標記錄所在的分組,然后在該分組內進行線性查找(因為分組內記錄數量較少,線性查找代價低)。使用最大主鍵值作為槽值的核心原因是:它使二分查找的決策更簡單、更高效,減少了比較操作的歧義,并能直接利用主鍵單調遞增的特性

1、為什么最大值優于最小值?

1.1、使用最大值時的二分查找邏輯??:當目標主鍵(Target Key)與槽值比較時:

  • 如果目標主鍵 <= 槽值(分組最大主鍵),則目標記錄可能位于該槽對應的分組或更早的分組(因為槽值是該分組的最大主鍵,目標值不超過最大值說明它可能在這個分組內)。
  • 如果目標主鍵 > 槽值,則目標記錄一定位于后續的分組(因為分組最大主鍵小于目標值,說明目標不在當前或之前的任何分組)。

? 這允許二分查找高效調整搜索范圍(例如,調整 high 或 low 指針),每次比較都能明確縮小搜索范圍,沒有歧義。

1.2、使用最小值時的二分查找問題??:如果槽記錄分組的最小主鍵值:

  • 如果目標主鍵 < 槽值(分組最小主鍵),則目標記錄一定位于更早的分組。
  • 如果目標主鍵 >= 槽值,則目標記錄可能位于該槽對應的分組或更晚的分組。

? 這種方式在比較時存在歧義:當目標主鍵 >= 槽值時,無法立即確定目標是否在分組內,因為分組最小主鍵只表示分組的起始點,但分組可能包含更大的值(例如,目標值可能落在兩個分組之間)。這會導致二分查找需要額外的檢查步驟(如檢查后一個槽的最小值),或多次線性探測,降低了效率。

簡單來說,使用最大值允許二分查找直接通過 target <= slot_value 條件鎖定目標分組,而最小值會導致條件模糊,查詢路徑更長。

2、結合二分法的詳細示例

下面通過一個具體例子說明。假設一個 InnoDB 數據頁包含以下主鍵值(已排序):1, 3, 5, 7, 9, 11, 13, 15。為簡化,假設每個分組包含2條記錄,頁目錄有4個槽:

分組:組1 (1, 3)、組2 (5, 7)、組3 (9, 11)、組4 (13, 15)。

現在,執行二分查找目標主鍵為10的記錄(10不存在,但查找過程相同)。

二分查找的偽代碼如下(以方案A和B分別演示)

# 通用二分查找框架(查找可能的分組索引)

low = 0

high = num_slots - 1

while low <= high:

??? mid = (low + high) // 2

??? if target <= slots[mid].value:? # 比較目標值和槽值

??????? high = mid - 1? # 目標在左半部分(包括當前槽)

??? else:

??????? low = mid + 1?? # 目標在右半部分

# 結束時,low 是可能的目標分組索引

方案A:使用最大值的二分查找(高效)

  • 槽值設置:槽0 = 3(組1最大主鍵)、槽1 = 7(組2最大主鍵)、槽2 = 11(組3最大主鍵)、槽3 = 15(組4最大主鍵)。
  • 槽值數組:[3, 7, 11, 15](槽索引:0,1,2,3)
  • 查找目標:10
  • 二分查找過程:
    • 初始:low = 0, high = 3
      • mid = (0 + 3) // 2 = 1, 槽值 = 7
      • 比較:10 <= 7? False → 目標 > 7,所以目標在槽1之后,設置 low = mid + 1 = 2
    • 更新:low = 2, high = 3
      • mid = (2 + 3) // 2 = 2, 槽值 = 11
      • 比較:10 <= 11? True → 目標可能位于槽2或更早分組,設置 high = mid - 1 = 1
    • 現在 low = 2, high = 1,low > high,循環結束。返回候選索引 low = 2(可能的目標分組)。
  • 結果:槽2被選中(對應組3)。然后在組3內線性查找記錄(9和11),發現10不存在。
  • 分析??:僅2次比較就鎖定了槽2(組3),因為最大值為11提供了明確的上界:10 <= 11表示目標一定在槽2之前的某個分組(或槽2本身),而前一步的 low 調整確保了高效收斂。整個查找過程直接,沒有歧義。

方案B:使用最小值的二分查找(低效)

  • 槽值設置:槽0 = 1(組1最小主鍵)、槽1 = 5(組2最小主鍵)、槽2 = 9(組3最小主鍵)、槽3 = 13(組4最小主鍵)。
  • 槽值數組:[1, 5, 9, 13](槽索引:0,1,2,3)
  • 查找目標:10
  • 二分查找過程:
    • 初始:low = 0, high = 3
      • mid = (0 + 3) // 2 = 1, 槽值 = 5
      • 比較:10 <= 5? False → 目標 > 5,但無法確定是否在槽1分組內(因為 min=5,目標可能位于槽1或后續分組),設置 low = mid + 1 = 2
    • 更新:low = 2, high = 3
      • mid = (2 + 3) // 2 = 2, 槽值 = 9
      • 比較:10 <= 9? False → 目標 > 9,同樣無法確定,設置 low = mid + 1 = 3
    • 更新:low = 3, high = 3
      • mid = (3 + 3) // 2 = 3, 槽值 = 13
      • 比較:10 <= 13? True → 目標可能位于槽3或更早分組,設置 high = mid - 1 = 2
    • 現在 low = 3, high = 2,low > high,循環結束。返回候選索引 low = 3(可能的目標分組)。
  • 結果:槽3被選中(對應組4)。但組4的最小主鍵是13 > 10,所以目標不在該分組。需要額外檢查前一個槽(槽2,組3)或直接線性掃描組3,才能確定10在組3范圍內(但不存在)。
  • ??分析??:使用了3次比較,但結束時 low=3 是錯誤的(組4最小主鍵13 > 10,目標不可能在組4)。二分查找后,必須額外檢查槽2的槽值(9),才能發現目標可能位于槽2分組(因為 9 <= 10 但 10 < 13)。整個路徑更長,存在歧義:當目標 > 槽值時,無法排除當前分組的可能性,導致 low 和 high 調整不精確。這會增加不必要的比較和分組訪問次數。

關鍵區別總結

  • 決策清晰性??:使用最大值時,槽值(最大主鍵)定義了分組的明確上界。二分查找中,target <= slot_value 直接表示目標位于索引 <= mid 的某個分組,從而高效縮小搜索范圍。最小值則只能定義分組的起始點,沒有上界信息,導致決策模糊。
  • ??效率??:最大值的二分查找平均只需 O(log N) 次比較(N是槽數),就能鎖定唯一可能的分組。最小值可能需要額外線性探測或回溯,增加開銷。
  • ??插入與范圍查詢??:在插入新記錄時,使用最大值也更容易處理邊界情況(如記錄插入到分組末尾)。對于范圍查詢(如 key BETWEEN A AND B),最大值可以快速排除不相關的分組。
  • ??單調性利用??:主鍵值單調遞增,使用最大值序列(如3,7,11,15)也單調遞增,恰好匹配二分查找要求。

設計背后的權衡

? InnoDB 選擇最大值是工程優化,犧牲少量內存(存儲最大值)換取查詢性能。分組大小(如默認每組6-8條記錄)也進行了權衡,確保二分查找快速收斂的同時,分組內線性查找成本低。實際實現中,InnoDB 的頁目錄還處理了記錄刪除、變長記錄等復雜情況,但最大值原則保持了二分查找的效率。

總之,槽記錄分組最大主鍵值而非最小值,是為了使二分查找在頁內定位記錄時更高效、直接,減少了歧義和額外操作,從而提升整體查詢性能。

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

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

相關文章

世賽背景下,中職物聯網應用與服務賽項實訓解決方案

一、世賽背景與物聯網應用賽項概述 1.1 世賽發展歷程及對中職教育的影響 世界技能大賽&#xff08;WorldSkills Competition&#xff0c;簡稱世賽&#xff09;自1950年創立以來&#xff0c;已經成為全球范圍內展示職業技能水平的重要賽事。截至2024年&#xff0c;世賽已成功舉…

【攻防篇】解決:阿里云docker 容器中自動啟動xmrig挖礦-- 實戰

文章目錄 場景一、問題二、原因三、解決方案1、控制臺處理2、 [清除與防護](https://blog.csdn.net/ladymorgana/article/details/148921668?spm1001.2014.3001.5501)1. 緊急處理&#xff1a;停止挖礦進程2. 清理被感染的容器3. 防護措施&#xff1a;防止再次被入侵4. 排查入侵…

飛算智造JavaAI:智能編程革命——AI重構Java開發新范式

文章目錄 引言&#xff1a;當傳統Java開發遇上AI一、技術架構解析1.1 核心架構圖1.2 關鍵技術棧 二、實戰演示&#xff1a;從需求到代碼的全AI輔助2.1 場景&#xff1a;電商優惠券系統開發2.2 代碼生成實例2.3 智能調試演示 三、與傳統開發模式對比測試3.1 基準測試數據3.2 典型…

[特殊字符] 分享裂變新姿勢:用 UniApp + Vue3 玩轉小程序頁面分享跳轉!

在如今流量成本日益攀升的移動互聯網時代&#xff0c;"用戶分享拉新" 成為了增長的重要策略。而微信小程序作為天然具備社交傳播力的平臺&#xff0c;提供了較完善的分享機制支持。本文將從實戰角度出發&#xff0c;手把手教你如何使用 uni-app Vue3 構建一個支持「…

[創業之路-458]:企業經營層 - 藍海戰略 - 重構價值曲線、整合產業要素、創造新需求

“重構價值曲線、整合產業要素、創造新需求”是藍海戰略中實現價值創新的核心路徑&#xff0c;它們構成了一個從內部優化到外部協同&#xff0c;再到市場顛覆的完整邏輯鏈條。以下從理論框架、實踐方法和企業案例三個維度展開分析&#xff1a; 一、重構價值曲線&#xff1a;打…

慢查詢引發對mysql索引的探索

目錄 一、索引分類 1.1 聚簇索引結構 1.2 非聚簇索引(二級索引) 1.3 主鍵索引 1.4 唯一索引 1.5 普通索引 1.6 前綴索引 1.7 聯合索引 1.8 索引下推 1.9 索引區分度 二、優化索引的方法 2.1 索引的特點 2.2 適合創建索引的情況 2.3 不適合創建索引的情況 2.4 優…

啟用不安全的HTTP方法

背景&#xff1a; 今天被安全檢測出一個這樣的問題&#xff1a;啟用不安全的HTTP方法。DELETE方法是用來調試web服務器連接的http方式&#xff0c;支持該方式的服務器文件可能被非法刪除&#xff1b;PUT方法用來向服務器提交文件&#xff1b;TRACE方法本用于客戶端測試到服務器…

fvcom 水深文件dep制作

fvcom 水深文件dep制作 fvcom 水深文件dep制作20250630 本次案例網格和水深展示 vv image Figure 1 Model domain 本次制作其它驅動文件的輸入文件為yellowsea.2dm 格式2dm; 文件內容格式詳細介紹參考&#xff1a; https://www.xmswiki.com/wiki/SMS:2D_Mesh_Files_*.2dm …

ViewModel是EventFlow-State映射

ViewModel負責組裝界面狀態State。引發State變換的原因有很多&#xff0c;比如用戶點擊某個按鈕&#xff0c;一次網絡請求受到應答&#xff0c;一次本地數據庫查詢返回結果等等。因此ViewModel是根據各種事件生成State的對象&#xff0c;換句話說&#xff0c;是一個從多個事件流…

javaweb Day2

PreparedStatement作用: 預編譯SQL語句并執行: 預防SQL注入問題 SQL注入:SQL注入是通過操作輸入來修改事先定義好的SQL語句&#xff0c;用以達到執行代碼對服務器進行攻擊的方法。

Java項目:基于SSM框架實現的中學教學管理系統【ssm+B/S架構+源碼+數據庫+畢業論文+開題報告】

摘 要 現代經濟快節奏發展以及不斷完善升級的信息化技術&#xff0c;讓傳統數據信息的管理升級為軟件存儲&#xff0c;歸納&#xff0c;集中處理數據信息的管理方式。本景海中學教學管理系統就是在這樣的大環境下誕生&#xff0c;其可以幫助管理者在短時間內處理完畢龐大的數據…

JVM調優實戰 Day 15:云原生環境下的JVM配置

【JVM調優實戰 Day 15】云原生環境下的JVM配置 文章標簽 jvm調優, 云原生, Java性能優化, JVM參數配置, 容器化部署, Kubernetes, Docker, JVM在云原生中的應用 文章簡述 隨著云原生技術的普及&#xff0c;Java 應用越來越多地運行在容器&#xff08;如 Docker&#xff09;和…

數據結構day7——文件IO

一、標準 IO 的起源與概念 標準 IO&#xff08;Standard Input/Output&#xff09;是由 Dennis Ritchie 在 1975 年設計的一套 IO 庫&#xff0c;后來成為 C 語言的標準組成部分&#xff0c;并被 ANSI C 所采納。它是對底層文件 IO 的封裝&#xff0c;提供了更便捷、可移植的文…

6.Docker部署ES+kibana

部署ES&#xff08;Elasticsearch&#xff09;kibana 1.ES暴露的端口很多 2.ES十分消耗內存 3.ES的數據一般需要掛載出去&#xff0c;放在安全目錄&#xff08;掛載) elastic 前往官方手冊 1.下載運行elasticsearch的 docker run -d --name elasticsearch --net somenet…

使用mysqldump對mysql數據庫進行備份

目錄 1軟件說明 2語法格式 3備份流程 3.1只備份指定數據庫中表和數據 3.1.1準備目錄 3.1.2備份db1數據庫里面的所有表信息 3.1.3還原備份 3.2備份數據庫結構 3.2.1備份db1數據庫的結構和數據 3.2.2還原數據庫 3.3備份所有數據庫 3.3.1備份數據庫 3.3.2還原數據庫 1…

vue3路由跳轉打開新頁面

Vue3 路由跳轉打開新頁面的方法 在 Vue3 中&#xff0c;有幾種方法可以實現路由跳轉時打開新頁面&#xff1a; 1. 使用 router.resolve 方法 import { useRouter } from vue-routerconst router useRouter()const openNewPage (path) > {const resolved router.resolv…

SeaTunnel 社區 2 項目中選“開源之夏 2025”,探索高階數據集成能力!

Apache SeaTunnel 社區在“開源之夏 2025”中再傳捷報&#xff0c;共有兩個項目成功入選&#xff0c;聚焦于 Flink CDC schema 支持與元數據管理的生態擴展方向&#xff0c;體現出 SeaTunnel 在實時數據集成和平臺化能力構建上的深入布局。 中選項目與學生如下&#xff1a; 《…

Neo4j無法建立到 localhost:7474 服務器的連接出現404錯誤

一、確認中文路徑問題&#xff08;核心原因&#xff09; 安裝路徑包含中文&#xff0c;可能導致 Windows 命令行或 Neo4j 解析路徑時出錯。 解決方法&#xff1a; 重新安裝 Neo4j 到英文路徑&#xff08;推薦&#xff09;&#xff1a; 將 Neo4j 解壓或安裝到不含中文的目錄&a…

鋰離子電池均衡拓撲綜述

鋰離子電池均衡拓撲綜述 一、引言 鋰離子電池因其高能量密度、長循環壽命等優點&#xff0c;在電動汽車、儲能系統等領域得到了廣泛應用。然而&#xff0c;電池組在使用過程中&#xff0c;由于電池個體差異、充放電管理等因素&#xff0c;會出現荷電狀態&#xff08;SOC&…

[面試] 手寫題-淺拷貝,深拷貝

淺拷貝 // 淺拷貝 function shallow(obj) {const newObj {}for (const key in obj) {// 保證 key 不是原型的屬性if (obj.hasOwnProperty(key)) {newObj[key] obj[key]}}return newObj }深拷貝 遞歸 O(n^2) // 深拷貝 function deepClone(obj {}) {// 如果傳入的是 null&am…