MySQL索引背后的B+樹奧秘

MySQL 索引實現機制深度解析

MySQL 索引的核心數據結構是 B+樹。這種設計是數據庫領域數十年優化的結果,完美平衡了磁盤 I/O 效率、范圍查詢性能和存儲利用率。以下是關鍵要點:


一、為什么選擇 B+樹而非其他結構?
數據結構劣勢B+樹優勢
二叉搜索樹深度不可控,極端情況退化成鏈表(O(n))多路平衡,高度穩定(O(log n))
B 樹數據存儲在內部節點,范圍查詢效率低數據全存葉子節點,順序訪問高效
哈希索引僅支持等值查詢,不支持范圍查詢,內存占用高天然支持范圍查詢(>、<、BETWEEN)和排序
跳表磁盤 I/O 不友好,存儲空間放大磁盤頁對齊設計,減少 I/O 次數

? B+樹核心優勢

  • 樹高通常僅 3-4 層(千萬級數據)
  • 葉子節點形成有序雙向鏈表,范圍查詢極快
  • 內部節點只存鍵值(不存數據),提升節點容量

二、B+樹索引的物理結構

以 InnoDB 存儲引擎為例:

根節點
內部節點
內部節點
葉子節點
葉子節點
葉子節點
葉子節點
  1. 葉子節點(Leaf Nodes)

    • 存儲完整數據行(聚簇索引)或主鍵值(二級索引)
    • 通過雙向鏈表連接,支持順序掃描
    • 默認每頁 16KB(可通過 innodb_page_size 調整)
  2. 內部節點(Internal Nodes)

    • 僅存儲索引鍵值 + 子節點指針
    • 單節點可存儲上千個鍵值(減少樹高)

三、索引類型與 B+樹實現差異
1. 聚簇索引(Clustered Index)
  • 物理存儲順序與索引順序一致
  • 葉子節點直接存數據行
  • 每表只有一個聚簇索引(通常為主鍵)
CREATE TABLE users (id INT PRIMARY KEY,  -- 聚簇索引name VARCHAR(50),INDEX idx_name(name) -- 二級索引
);
2. 二級索引(Secondary Index)
  • 葉子節點存儲主鍵值(非數據行)
  • 查詢需回表:先查二級索引 → 再查聚簇索引
  • 覆蓋索引可避免回表(索引包含所有查詢字段)
-- 回表查詢(需兩次B+樹查找)
SELECT * FROM users WHERE name = 'Alice';-- 覆蓋索引(避免回表)
SELECT id FROM users WHERE name = 'Alice';
3. 聯合索引(Composite Index)
  • 按字段順序構建 B+樹
  • 最左前綴匹配原則生效
-- 創建聯合索引
CREATE INDEX idx_age_name ON users(age, name);-- 生效場景
SELECT * FROM users WHERE age = 30;                 -- ? 使用索引
SELECT * FROM users WHERE age = 30 AND name = 'Bob';-- ? 使用索引
SELECT * FROM users WHERE name = 'Bob';             -- ? 不滿足最左前綴

四、B+樹操作原理
插入流程
  1. 定位到葉子節點插入位置
  2. 若節點未滿 → 直接插入
  3. 若節點已滿 → 分裂節點(50%數據移入新頁)
  4. 向上遞歸更新父節點指針
刪除流程
  1. 定位葉子節點中的記錄
  2. 設置刪除標記(InnoDB 使用 purge 線程異步清理)
  3. 若節點利用率過低 → 合并相鄰節點

五、性能優化實踐
  1. 控制索引字段長度

    • 使用前綴索引:INDEX idx_name(name(10))
    • 整型優于字符串(更小鍵值 → 更高節點密度)
  2. 避免索引分裂熱點

    • 不使用單調遞增主鍵(如 UUID v4 代替自增 ID)
    CREATE TABLE orders (id BINARY(16) PRIMARY KEY  -- UUID v4
    );
    
  3. 索引選擇性優化

    • 選擇性 > 30% 時索引才有效
    -- 計算字段選擇性
    SELECT COUNT(DISTINCT status)/COUNT(*) FROM orders; 
    

六、其他索引類型的實現
索引類型實現結構適用場景
全文索引(FULLTEXT)倒排索引MATCH(content) AGAINST('keyword')
空間索引(SPATIAL)R 樹GIS 地理位置查詢
內存表哈希索引哈希表臨時表/等值查詢高頻場景

七、診斷索引使用情況
1. 查看索引樹高度
-- InnoDB 索引統計
ANALYZE TABLE users;
SELECT index_name, stat_value AS pages
FROM mysql.innodb_index_stats 
WHERE table_name = 'users'
AND stat_name = 'n_leaf_pages';
  • 樹高計算公式:h = log_N(葉子頁數)
    (N = 單頁可存儲鍵值數,通常 1000+)
2. EXPLAIN 解析索引使用
EXPLAIN SELECT * FROM users WHERE age > 25;
  • type: ref → 索引查找
  • Extra: Using index → 覆蓋索引

總結:MySQL 索引設計哲學

  1. 磁盤友好優先
    B+樹節點大小 = 磁盤頁大小(16KB),最大化順序 I/O
  2. 寫優化讓步于讀優化
    索引維護成本(分裂/合并)換取高效查詢
  3. 空間換時間
    索引占存儲空間 20%-30%,但提升查詢速度 10-100 倍

黃金法則

  • 更新頻繁的表避免過多索引
  • 聯合索引字段順序:高選擇性在前
  • 長文本用前綴索引 + 全文索引互補

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

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

相關文章

k8s通過NUMA親和分配GPU和VF接口

問題 一般情況下&#xff0c;sriov插件和gpu分配插件是單獨工作的&#xff0c;網卡和GPU沒有根據連接關系分配 如果一個節點起了多個容器&#xff0c;會造成GPU和網卡的通信瓶頸 修改 如果一個點起兩個容器&#xff0c;可以按照NUMA親和來分配 修改kubelet配置文件/var/lib/kub…

qemu-img 擴容虛擬機磁盤后擴容文件系統

在給磁盤映像擴容前需要關閉虛擬機1. 關閉虛擬機 [rootkvm1 opt]# virsh shutdown centos7.9 [rootkvm1 opt]# virsh list --allId Name State ----------------------------- centos7.9 shut off[rootkvm1 opt]# qemu-img info /var/lib/libvirt/images/centos…

Winwos上編譯opencv的GPU版本推理yolov8

1.工具 VS2019 opencv4.7.0 opencv_contrib4.7.0 Cmake3.27.0 cudnn-windows-x86_64-8.5.0.96_cuda11-archive 2.具體流程 1.配置路徑和編譯器后點擊configure 2.提前下載相關的包&#xff0c;如下圖所示 3.第一次configure完成后&#xff0c;需要再配置編譯選項 在編譯…

C語言案例《猜拳游戲》

《猜拳游戲》 游戲說明 一、游戲簡介 本游戲為猜拳對戰類游戲&#xff0c;玩家可選擇不同對手進行石頭、剪刀、布的猜拳對決&#xff0c;支持重復游玩&#xff0c;直至玩家選擇退出。 二、游戲流程 選擇對手 游戲開始后&#xff0c;玩家需從 3 名對手中選擇 1 名進行對戰&#…

使用python的頭文件Matplotlib時plt.show()【標題字體過小】問題根源與解決方案

使用python的頭文件Matplotlib時plt.show【標題字體過小】問題根源與解決方案1. 問題復現2. 問題分析3. 解決方案方案一&#xff08;推薦&#xff09;&#xff1a;使用 fig.suptitle 結合 subplots_adjust方案二&#xff1a;以保存文件函數plt.savefig為準方案三&#xff1a;不…

全面解析MySQL(3)——CRUD進階與數據庫約束:構建健壯數據系統的基石

> 本文將帶你深入探索MySQL的進階CRUD操作與核心約束機制,用設計原則的視角揭示數據庫如何保障數據世界的秩序。 ### 一、進階CRUD:數據操作的精密工具 #### 1. 精準篩選:WHERE子句的深度運用 ```sql -- 基礎篩選:價格大于50的菜品 SELECT * FROM dishes WHERE pric…

使用Redis實現MySQL的數據緩存

使用Redis來實現/mySQL的數據緩存的架構1&#xff1a;目標數據從mySQL讀取數據或者從Redis讀取數據 2&#xff1a;使用cannal監控mySQL&#xff1a;canal-server可以對mysql的blog實行拉取&#xff0c;可以拉去blog里面的(增&#xff0c;刪&#xff0c;改等操作&#xff0c;查詢…

linux配置ntp時間同步

目錄 1.設置時區 2.安裝chrony時間同步工具 3.修改chrony配置文件,添加阿里云NTP服務器作為時鐘源 4.重啟chrony服務&#xff0c;并查看同步結果 1.設置時區 timedatectl set-timezone Asia/Shanghai 2.安裝chrony時間同步工具 apt install chrony -y&#xff08;dnf ins…

powershell 實現批量把文件夾下的bmp文件轉換為jpg

以下是一個使用PowerShell將BMP圖像批量轉換為JPG&#xff08;質量85&#xff09;的腳本&#xff1a; <# .SYNOPSIS批量將BMP圖像轉換為JPG格式&#xff08;質量85&#xff09; .DESCRIPTION此腳本會遍歷指定文件夾中的所有BMP文件&#xff0c;并將它們轉換為JPG格式&#x…

星圖云開發者平臺新功能速遞 | 頁面編輯器:全場景編輯器,提供系統全面的解決方案

在數字化轉型的浪潮下&#xff0c;高效的低代碼開發工具成為企業和開發者的剛需&#xff0c;其需要針對Web、APP、H5等不同終端快速構建應用。但不同場景的開發往往需要不同的工具和技術棧&#xff0c;導致開發效率低、協作成本高。星圖云開發者平臺創新推出多類型頁面專用編輯…

激活函數Focal Loss 詳解?

Focal Loss 詳解?1. 背景?Focal Loss 是由 Lin et al. (2017) 在論文 《Focal Loss for Dense Object Detection》 中提出的一種損失函數&#xff0c;主要用于解決 目標檢測&#xff08;Object Detection&#xff09; 中的 類別不平衡問題&#xff0c;特別是在 One-Stage 檢測…

Python 鏈接各種中間件[Mysql\redis\mssql\tdengine]

文章目錄鏈接參數設置logger 日志redis 鏈接mysql 鏈接emqx 鏈接mssql 鏈接tdengine 鏈接采集OPCUA的點表的配置信息設備點表OPCUA 采集 數據程序數據采集邏輯鏈接參數 import randomtdengine_connection_params {username: root,password: taosdata,host: 127.0.0.1,port: 6…

C Primer Plus 第6版 編程練習——第11章(上)

本章共16題&#xff0c;分上中下三篇1.設計并測試一個函數&#xff0c;從輸入中獲取n個字符&#xff08;包括空白、制表符、換行符)&#xff0c;把結果存儲在一個數組里&#xff0c;它的地址被傳遞作為一個參數。int get_n_char(char arr[], int n) {int i 0;char ch;while (i…

Java開發崗面試記錄合集

一、Java 核心1. 基礎語法final關鍵字的作用修飾類&#xff1a;類不可被繼承&#xff08;如String類&#xff09;&#xff0c;保證類的穩定性和安全性。修飾方法&#xff1a;方法不可被重寫&#xff08;防止子類篡改父類核心邏輯&#xff0c;如工具類方法&#xff09;。修飾變量…

Linux 系統時間設置(date 和 ntpdate)-linux028

date 命令&#xff1a;查看或設置系統時間1. 查看當前時間date示例輸出&#xff1a;Tue Mar 4 01:36:45 CST 20142. 設置時間&#xff08;不設置日期&#xff09;date -s 09:38:40設置后輸出&#xff1a;Tue Mar 4 09:38:40 CST 20143. 設置完整日期和時間&#xff08;推薦格…

iOS上使用WebRTC推拉流的案例

一、庫集成 首先&#xff0c;確保在你的 Podfile 中添加依賴&#xff1a; pod GoogleWebRTC然后執行 pod install 安裝庫。 二、代碼示例 2.1、權限配置&#xff1a;在 Info.plist 中添加攝像頭、麥克風權限 <!-- 需要在 Info.plist 中添加以下權限 --> <key>NSCam…

API: return response as HTML table

想要把response table變成HTML的table&#xff0c;即想達到下面這種的話<table boarder"1" style"width:100%; boarder-collapse: collapse; text-align:left"><tr><th>Customer</th><th>Date</th><th>Debit Am…

OneNote 當前無法同步筆記。將繼續嘗試。 (錯誤代碼: 0xE00009C8 bb0ur)問題解決

之前因為同步錯誤&#xff0c;導致OneNote一個筆記本內容全部消失&#xff0c;筆記本內容如下圖同步狀態和錯誤如下&#xff1a;提醒錯誤為&#xff1a;OneNote 當前無法同步筆記。將繼續嘗試。 (錯誤代碼: 0xE00009C8 bb0ur)當時心態有點崩&#xff0c;也是查了好些資料&#…

OneCode3.0 Gallery 組件前后端映射機制:從注解配置到前端渲染的完整鏈路

一、注解體系與前端組件的映射基礎 ? OneCode Gallery 組件實現了 Java 注解與前端 UI 組件的深度綁定&#xff0c;通過GalleryAnnotation、GalleryItemAnnotation和GalleryViewAnnotation三個核心注解&#xff0c;構建了從后端配置到前端渲染的完整鏈路。這種映射機制的核心價…

規則分配腳本

需求&#xff1a; 1.根據用戶編寫的要報規則,去mysql庫里SysManage_Rule表獲取已經啟用的規則作為條件&#xff08;例如[{“field”: “關鍵詞”, “logic”: “AND”, “value”: “阿爾法”, “operator”: “”&#xff0c;, “assign_user”: “user222”}]&#xff09;條…