MYSQL-索引篇

索引結構

概述

MySQL 的索引是在存儲引擎層實現的,不同的存儲引擎有不同的索引結構,主要包含以下幾種:

索引結構描述
B+Tree索引最常見的索引類型,大部分引擎都支持 B+ 樹索引
Hash索引底層數據結構是用哈希表實現的,只有精確匹配索引列的查詢才有效,不支持范圍查詢
R-tree(空間索引)空間索引是MyISAM引擎的一個特殊索引類型,主要用于地理空間數據類型,通常使用較少
Full-text(全文引)

是一種通過建立倒排索引,快速匹配文檔的方式。類似于Lucene,Solr,ES

MySQL 中所支持的所有的索引結構,接下來,我們再來看看不同的存儲引擎對于索引結構的支持情況。

索引InnoDBMyISAMMemory
B+tree索引支持支持支持
Hash 索引不支持不支持支持
R-tree 索引不支持支持不支持
Full-text5.6版本之后支持支持不支持

注意:我們平常所說的索引,如果沒有特別指明,都是指B+樹結構組織的索引。

具體實現

B-Tree與B+Tree

B-Tree

B-Tree,B樹是一種多叉路衡查找樹,相對于二叉樹,B樹每個節點可以有多個分支,即多叉。

以一顆最大度數(max-degree)為5(5階)的b-tree為例,那這個B樹每個節點最多存儲4個key,5個指針:

B+Tree

B+Tree是B-Tree的變種,我們以一顆最大度數(max-degree)為4(4階)的b+tree為例,來看一下其結構示意圖:

我們可以看到,兩部分:

  • 綠色框框起來的部分,是索引部分,僅僅起到索引數據的作用,不存儲數據。

  • 紅色框框起來的部分,是數據存儲部分,在其葉子節點中要存儲具體的數據。

B+Tree 與 B-Tree 的區別

最終我們看到,B+Tree 與 B-Tree 相比,主要有以下三點區別:

  • 所有的數據都會出現在葉子節點。

  • 葉子節點形成一個單向鏈表。

  • 非葉子節點僅僅起到索引數據作用,具體的數據都是在葉子節點存放的。

上述我們所看到的結構是標準的 B+Tree 的數據結構,接下來,我們再來看看 MySQL 中優化之后的 B+Tree。

MySQL 索引數據結構對經典的 B+Tree 進行了優化。在原 B+Tree 的基礎上,增加一個指向相鄰葉子節點的鏈表指針,就形成了帶有順序指針的 B+Tree,提高區間訪問的性能,利于排序。

頁(Page)的概念與作用

在關系型數據庫(如 MySQL InnoDB、Oracle、SQL Server 等)中,最常用的索引結構是 B+ 樹(或其變種)。B+ 樹索引在磁盤或持久化存儲上,都是以“頁(page)”為最小 I/O 單元來管理的

  1. 頁(Page)是什么?

    • 頁(也稱數據頁、塊 block)是數據庫讀寫時的最小單位,典型大小為 4?KB、8?KB 或 16?KB。

    • 每個頁在內存中對應一個緩沖區幀(buffer frame),從磁盤讀入時,整個頁一起加載;修改時,整個頁也會被標記為“臟頁”并遲緩寫回。

  2. 為什么要用頁?

    • I/O 單元磁盤和 OS 的 I/O 都是按頁(或塊)做的,讀寫整頁比逐條讀寫要高效得多。

    • 緩存管理:數據庫的 Buffer Pool 也是以頁為單位進行加載和置換。

    • 空間管理:頁作為固定大小的容器,便于分配、回收和查找空閑空間。

B+ 樹的邏輯結構與頁的映射

┌───────────┐┌──────?│ Internal  │?──────┐│ ? ? ? │  page(s)  │ ? ? ? ││ ? ? ? └───────────┘ ? ? ? │┌──┴──┐ ? ? ? ? ? ? ? ? ?  ┌───┴──┐│ ... │ ? ? ? ? ? ? ? ? ?  │ ...  │└──┬──┘ ? ? ? ? ? ? ? ? ?  └───┬──┘│ ? ? ? ┌───────────┐ ? ? ? │└──────?│ Leaf page │?──────┘└───────────┘
  1. 內部節點(Internal node)對應一個或多個頁

    • 存放 鍵值 + 子節點指針(頁號或內存指針)。

    • 用于路由查找:從根開始,根據鍵值范圍逐層向下定位到葉子頁。

  2. 葉子節點(Leaf node) 對應一系列連續頁

    • 真正存放 完整的索引記錄聚簇索引的全行數據

    • 通常包含:

      • 索引鍵(Key)

      • 若是非聚簇索引,則附帶 主鍵 作為“行定位指針”;

      • 若是聚簇索引(Clustered Index),葉子頁直接存放整行數據。

  3. 頁之間的鏈表

    • 葉子頁還會雙向鏈成一個鏈表,方便范圍掃描;

    • 內部節點頁在分裂/合并時,也可能維護兄弟指針或在父節點更新。

頁內記錄的組織

  1. 頁頭(Header)

    • 存放頁類型(內部/葉子)、當前記錄數、Free Space 指針、鏈表指針(前驅/后繼頁號)等元信息。

  2. 記錄目錄(Slot Array)

    • 有些數據庫(如 InnoDB)在頁尾維護一個 Slot Array,存放每條記錄在頁內的偏移。

    • 插入/刪除只需調整 Slot Array 及相應記錄位置,避免大量移動。

  3. 記錄存儲(Record Storage)

    • 記錄以物理或邏輯順序(根據索引鍵)存儲在頁的主體區域。

    • 有的系統支持 前綴壓縮:只存儲鍵的增量部分,減少空間。

  4. 空閑空間管理(Free Space)

    • 頁頭維護一個指向空閑區(free space)的指針;新記錄優先填滿空閑區,再觸發分裂。

頁分裂與合并

頁分裂(Page Split)
  • 觸發:當插入一條記錄到已無足夠空閑空間的葉子頁或內部頁時。

  • 過程

    1. 分配一個“同級”新頁;

    2. 將原頁中大約一半偏后的記錄(或指針)移動到新頁;

    3. 在父節點中插入一個新的鍵和指向新頁的指針;若父頁也滿,則遞歸向上分裂。

  • 影響

    • 寫放大:要寫兩個頁(原頁&新頁)及更新父頁;

    • 碎片化:原本連續的邏輯鍵可能跨兩個頁,影響范圍掃描的 I/O 連續性;

    • 內存/緩存抖動:新頁要加載到內存,可能驅逐其他頁面。

頁合并(Page Merge)
  • 觸發:當刪除操作導致某頁的記錄數低于某個閾值(例如空閑空間過大),并且相鄰頁也較空時。

  • 過程:把兩個兄弟頁的記錄合并到一頁,釋放一個頁號,并相應在父節點刪除指針;若父節點太空,也可遞歸向上合并。


順序 vs. 隨機主鍵對頁分裂的影響

  • 順序主鍵(自增、時間戳)

    • 新記錄總插入到葉子頁的最右端,

    • 只會在最右頁“尾部”分裂;

    • 降低對中間頁的頻繁分裂,保證大部分頁都被順序填滿。

  • 隨機/無序主鍵(UUID、散列)

    • 每次插入可以分散到任何葉子頁,

    • 導致各頁隨機“爆滿”并分裂,

    • 頻繁觸發分裂,帶來更高的寫放大和碎片率。

索引分類

索引分類

在MySQL數據庫,將索引的具體類型主要分為以下幾類:主鍵索引、唯一索引、常規索引、全文索引。

分類含義特點關鍵字
主鍵索引針對表中主鍵創建的索引默認自動創建,只能有一個PRIMARY
唯一索引避免同一個表中某數據列中的值重復可以有多個UNIQUE
常規索引快速定位特定數據可以有多個
全文索引全文索引查找的是文本中的關鍵詞,而不是比較索引中的值可以有多個FULLTEXT

聚集索引 & 二級索引

而在 InnoDB 存儲引擎中,根據索引的存儲形式,又可以分為以下兩種:

分類含義特點
聚集索引 (Clustered Index)將數據存儲與索引放到了一塊,索引結構的葉子節點保存了行數據必須有,而且只有一個
二級索引 (Secondary Index)將數據與索引分開存儲,索引結構的葉子節點關聯的是對應的主鍵可以存在多個

聚集索引選取規則:

  • 如果存在主鍵,主鍵索引就是聚集索引。

  • 如果不存在主鍵,將使用第一個唯一 (UNIQUE) 索引作為聚集索引。

  • 如果表沒有主鍵,或沒有合適的唯一索引,則 InnoDB 會自動生成一個 rowid 作為隱藏的聚集索引。

查找過程-回表查詢

接下來,我們來分析一下,當我們執行如下的SQL語句時,具體的查找過程是什么樣子的

具體過程如下:

①. 由于是根據name字段進行查詢,所以先根據name='Arm'到name字段的二級索引中進行匹配查找。但是在二級索引中只能查找到Arm對應的主鍵值10。

②. 由于查詢返回的數據是*,所以此時,還需要根據主鍵值10,到聚集索引中查找10對應的記錄,最終找到10對應的行row。

③. 最終拿到這一行的數據,直接返回即可。

這個過程也稱為回表查詢

回表查詢: 這種先到二級索引中查找數據,找到主鍵值,然后再到聚集索引中根據主鍵值,獲取

數據的方式,就稱之為回表查詢。

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

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

相關文章

(純新手教程)HTML零基礎教學

(下一章:python網絡爬蟲)HTML 簡介HTML(HyperText Markup Language,超文本標記語言)是用于創建網頁的標準標記語言。什么是 HTML?HTML 不是編程語言,而是一種標記語言使用標簽來描述…

前端面試寶典---項目難點2-智能問答對話框采用虛擬列表動態渲染可視區域元素(10萬+條數據)

引言 在我參與智能問答項目中一個智能體回話并不會像豆包一樣,每次新建會話都是是從頭開始,而項目中你想創建新會話就像chatbox一樣,是點擊橡皮擦開啟新的聊天上下文,但是直接的聊天記錄依然存在,針對超過十萬&#xf…

Python元組:不可變數據的強大用法

文章目錄元組概念1.基本特性2.創建元組3.訪問元素4.元組的不可變性5.元組操作6.元組解包7.命名元組8.元組與列表的比較9.元組的優勢10.適用場景11.常用方法小結元組 概念 元組是 Python 中一個非常重要的內置數據結構,它與列表(list)相似但具有關鍵差異。下面我將…

若爾蓋濕地的花湖

花湖位于若爾蓋縣和甘肅的郎木寺之間的213國道旁,屬于若爾蓋濕地國家級自然保護區內。又名“梅朵湖”,因陽光照射下湖面色彩斑斕如絢麗的花瓣得名。花湖的大門是梯形高大石柱搭成,我們需要過天橋到對面檢票坐小交通。通過車窗看到一層一層的云…

50天50個小項目 (Vue3 + Tailwindcss V4) ? | DoubleClickHeart(雙擊愛心)

&#x1f4c5; 我們繼續 50 個小項目挑戰&#xff01;—— DoubleClickHeart組件 倉庫地址&#xff1a;https://github.com/SunACong/50-vue-projects 項目預覽地址&#xff1a;https://50-vue-projects.vercel.app/ 使用 Vue 3 的 Composition API&#xff08;<script se…

1-緒論-1-數據結構的基本概念

&#x1f389; 數據結構的魔法世界&#x1f4da;&#x1f468;?&#x1f393;“數據就像大海中的浪花&#xff0c;結構則是那神秘的洋流。掌握數據結構&#xff0c;就是掌握在信息海洋中自由航行的力量&#xff01;”引言&#xff1a;為什么要學數據結構&#xff1f;&#x1f…

linux網絡相關命令簡介

目錄 一、IP命令 1、Link或L:管理網絡接口(網卡) 2、Address或Addr,A:管理Ip地址 3、Route或R:管理路由表

教育培訓機構如何為課程視頻添加防盜錄的強水印?

在知識付費時代&#xff0c;教育培訓機構的課程視頻是核心資產&#xff0c;但盜錄、非法傳播等問題卻讓機構防不勝防。如何在不影響學員觀看體驗的前提下&#xff0c;為課程視頻添加“強效防盜水印”&#xff0c;精準追蹤泄露源頭&#xff1f;本文將為您揭秘高安全性水印的添加…

python的形成性考核管理系統

前端開發框架:vue.js 數據庫 mysql 版本不限 后端語言框架支持&#xff1a; 1 java(SSM/springboot)-idea/eclipse 2.NodejsVue.js -vscode 3.python(flask/django)–pycharm/vscode 4.php(thinkphp/laravel)-hbuilderx 數據庫工具&#xff1a;Navicat/SQLyog等都可以 摘要 隨著…

A*算法詳解

A*算法詳解一、A*算法基礎概念1.1 算法定位1.2 核心評估函數1.3 關鍵數據結構二、A*算法的核心步驟三、啟發函數設計3.1 網格地圖中的啟發函數3.2 啟發函數的選擇原則三、Java代碼實現四、啟發函數的設計與優化4.1 啟發函數的可采納性4.2 啟發函數的效率影響4.3 常見啟發函數對…

.net winfrom 獲取上傳的Excel文件 單元格的背景色

需求&#xff1a;根據Excel某行標注了黃色高亮顏色&#xff0c;說明該行數據已被用戶選中(Excel文件中并沒有“已選中”這一列&#xff0c;純粹用顏色表示)&#xff0c;導入數據到數據庫時標注此行已選中直接上代碼&#xff1a;//選擇Excel文件private void btnBrowse_Click(ob…

OpenAI GPT-4o技術詳解:全能多模態模型的架構革新與生態影響

本文由「大千AI助手」原創發布&#xff0c;專注用真話講AI&#xff0c;回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關注我&#xff0c;一起撕掉過度包裝&#xff0c;學習真實的AI技術&#xff01; ?? 一、核心定義與發布背景 官方定位 GPT-4o&#xff08;“o”代表“…

? 構建真正的高性能即時通訊服務:基于 Netty 集群的架構設計與實現

引子 在前面的文章中&#xff0c;我們基于 Netty 構建了一套單體架構的即時通訊服務。雖然單體架構在開發初期簡單高效&#xff0c;但隨著用戶量的增長和業務規模的擴大&#xff0c;其局限性逐漸顯現。當面對高并發場景時&#xff0c;單體 Netty 服務很容易觸及性能天花板&…

原來時間序列挖掘這么簡單

先搞懂&#xff1a;啥是時間序列&#xff1f;簡單說&#xff0c;時間序列就是按時間順序記下來的數據。比如&#xff1a;你每天早上 8 點測的體重&#xff0c;連起來就是 “體重時間序列”&#xff1b;超市每天的銷售額&#xff0c;連起來就是 “銷售時間序列”&#xff1b;城市…

基于Python的豆瓣圖書數據分析與可視化系統【自動采集、海量數據集、多維度分析、機器學習】

文章目錄有需要本項目的代碼或文檔以及全部資源&#xff0c;或者部署調試可以私信博主項目介紹每文一語有需要本項目的代碼或文檔以及全部資源&#xff0c;或者部署調試可以私信博主 項目介紹 豆瓣圖書數據智能分析系統是一個集數據采集、清洗、分析與可視化于一體的綜合性項…

2.3 數組與字符串

學習目標&#xff1a; 理解數組和字符串的概念&#xff08;存儲多個數據的“盒子”&#xff09;。掌握數組的聲明、初始化和遍歷方法。能用字符串處理簡單文本問題&#xff08;如字符計數、回文判斷&#xff09;。1 一維數組 基本概念 比喻&#xff1a; 數組就像“儲物柜”&…

C# 網口demo

bool _testStatus false; private void btnOpsStart_Click(object sender, EventArgs e) {int delay Convert.ToInt32(txtdelay.Text.Trim());txtView.Clear();txtView.AppendText("******************************************開始烤機*******************************…

MATLAB 安裝 ACADO 的完整步驟

? MATLAB 安裝 ACADO 的完整步驟 &#x1f4e6; 一、準備工作 1. 下載 ACADO Toolkit 官方地址&#xff1a;https://github.com/acado/acado 2. 解壓 ACADO 到你指定的路徑&#xff0c;例如&#xff1a; D:\user\acado-master建議路徑中 不要包含中文或空格。 &#x1f9f…

[逆向工程]160個CrackMe入門實戰之Afkayas.1.Exe解析(二)

[逆向工程]160個CrackMe入門實戰之Afkayas.1.Exe解析&#xff08;二&#xff09; 一、前言 在逆向工程的學習路徑上&#xff0c;CrackMe程序是初學者最好的練手材料。今天我們要分析的是160個CrackMe系列的第二題——Afkayas.1.Exe。這個程序由Afkayas編寫&#xff0c;難度為★…

本地電腦安裝Dify|內網穿透到公網

1.安裝Docker Docker: Accelerated Container Application Development 2.添加 PATH 3.安裝Dify https://github.com/langgenius/dify.git 把.env.example文件名改為.env 4.更換鏡像源 {"builder": {"gc": {"defaultKeepStorage": "20G…