MySQL InnoDB 存儲引擎的索引詳解

在 MySQL 中,InnoDB 是最常用的存儲引擎,它支持事務、行級鎖和外鍵約束等功能,而索引則是提升數據庫查詢性能的關鍵。在 InnoDB 存儲引擎中,索引不僅僅是提高查詢速度的工具,還是數據庫的核心組成部分之一。本文將詳細介紹 InnoDB 存儲引擎的索引結構、索引種類、索引優化技巧以及索引失效等方面的知識。

1. InnoDB 索引的結構

在 InnoDB 存儲引擎中,索引主要分為兩種類型:聚集索引(Clustered Index)非聚集索引(Non-clustered Index)

1.1 聚集索引(Clustered Index)
  • 聚集索引的葉子節點存儲的是數據行本身。換句話說,數據行的實際數據存儲在索引結構中,索引的順序就是數據的物理存儲順序。
  • 每個表只能有一個聚集索引,通常是主鍵索引。
  • 聚集索引通過將表的數據按索引順序存儲,從而提高了對主鍵字段查詢的效率。
1.2 非聚集索引(Non-clustered Index)
  • 非聚集索引的葉子節點并不存儲數據行本身,而是存儲數據行的指針(通常是聚集索引的主鍵值)。因此,查詢時需要通過指針再次訪問數據行。
  • 一個表可以有多個非聚集索引。
1.3 InnoDB 索引的 B+ 樹結構

InnoDB 存儲引擎中的聚集索引和非聚集索引通常都是基于 B+ 樹(自平衡的樹狀數據結構)來實現的。B+ 樹有以下特點:

  • 平衡性:所有葉子節點都位于同一層,因此查詢的時間復雜度是 O(log N)。
  • 有序性:葉子節點之間按照大小順序排列,可以進行范圍查詢。
  • 高效的插入和刪除操作:通過自平衡機制,插入和刪除操作能保持樹的平衡。

2. InnoDB 索引的類別

InnoDB 支持以下幾種類型的索引:

2.1 主鍵索引(Primary Key Index)
  • 主鍵索引是一種特殊的聚集索引,用來確保表中每一行的唯一性。InnoDB 表默認使用主鍵作為聚集索引。
  • 如果沒有顯式定義主鍵,InnoDB 會自動選定一個唯一索引作為主鍵。
2.2 唯一索引(Unique Index)
  • 唯一索引保證索引列的值是唯一的,但允許 NULL 值存在(多個 NULL 值也被視為不同的值)。
  • 唯一索引可以用于加速查詢。
2.3 普通索引(Index)
  • 普通索引是最常見的索引類型,它沒有唯一性約束,僅用于提高查詢效率。
  • 可以用于加速查詢,但不保證數據唯一性。
2.4 全文索引(Fulltext Index)
  • 全文索引是專門用于對文本字段進行全文檢索的索引類型。通常用于查找包含某個關鍵詞的文本數據。
  • 只適用于 CHARVARCHARTEXT 類型的列。
2.5 空間索引(Spatial Index)
  • 空間索引主要用于對空間數據類型(如 GEOMETRY)進行查詢優化。它使用的是 R 樹(Region Tree)而不是 B+ 樹。

3. 索引的最左前綴原則

InnoDB 索引遵循 最左前綴原則。也就是說,當你使用復合索引(由多個列組成的索引)時,索引的查詢可以使用到最左側的一部分索引。

舉個例子:

假設有一個復合索引 (a, b, c),那么查詢時,可以利用以下的前綴索引:

  • (a):只使用列 a,是有效的。
  • (a, b):使用列 a 和列 b,是有效的。
  • (a, b, c):使用列 abc,是有效的。

但如果你只使用 (b)(c) 作為查詢條件,MySQL 將無法使用這個復合索引,因為它沒有按照最左前綴的順序來查詢。


4. 索引覆蓋(Covering Index)

索引覆蓋是指查詢中涉及到的所有列都包含在索引中,從而避免了對表數據的訪問。換句話說,查詢的數據完全通過索引獲取,無需回表操作。

舉個例子:

假設有一個復合索引 (a, b, c),并且你執行了如下查詢:

SELECT a, b FROM table WHERE a = 1;

如果索引 (a, b, c) 已經包含了查詢所需的列 ab,那么 MySQL 可以直接從索引中獲取數據,而不需要回到表中去查詢。

索引覆蓋的好處是能顯著提高查詢性能,尤其是在大數據量的表中。

5. 索引下推(Index Condition Pushdown,ICP)

索引下推是一種優化技術,它能夠將查詢條件推送到存儲引擎的索引掃描階段,而不是等到讀取數據行時再進行過濾。這樣可以減少需要讀取的數據行數量,提升查詢效率。

  • 在執行查詢時,MySQL 會盡可能地將條件應用到索引掃描的階段,而不是僅僅依賴于后續的行級過濾。

例如,

SELECT * FROM Employees WHERE age > 30 AND salary like '%5000'

其中聯合索引(age、salary);

沒有索引下推時,執行這條語句的流程:

  • 1、存儲引擎使用聯合索引查出age>30的二級索引數據(葉子節點中有age、salary、主鍵);

  • 2、拿到主鍵回表,到聚簇索引中拿到完整記錄;

  • 3、將所有的完整記錄返回到server層(服務器層),再進行salary的模糊查詢。

開啟索引下推后,執行流程:

  • 1、存儲引擎使用聯合索引查出age>30的二級索引數據(葉子節點中有age、salary、主鍵);

  • 2、直接在二級索引數據中對salary進行模糊查詢。

可以看出索引下推之后減少了回表的次數,從而降低了查詢的時間。

6. 索引合并(Index Merge)

索引合并是 MySQL 在某些情況下使用的一個優化技術。當查詢條件涉及多個索引時,MySQL 會嘗試將多個索引的結果合并起來,從而加快查詢速度。

舉個例子:

假設有兩個索引:idx_aidx_b,查詢條件是:

SELECT * FROM table WHERE a = 1 OR b = 2;

MySQL 可以使用索引合并策略,首先分別從 idx_aidx_b 中找到符合條件的記錄,然后將它們合并,最后返回結果。

7. 索引失效的情況

索引并不是總能在所有情況下發揮作用。在以下情況下,索引可能會失效:

7.1 使用了不等于操作符(!=<>
SELECT * FROM table WHERE a != 1;

索引無法有效利用,因為不等于操作會導致掃描整個數據集。

7.2 使用了 OR 連接多個條件
SELECT * FROM table WHERE a = 1 OR b = 2;

當查詢條件中包含多個列的 OR 時,索引可能無法有效地優化查詢,尤其是當 OR 連接的列沒有單獨建立索引時。

7.3 使用函數
SELECT * FROM table WHERE YEAR(date_column) = 2023;

在where語句中使用函數(如 YEAR())會導致索引失效,因為索引是基于列值進行查找的,函數的使用會改變查詢模式。

7.4 LIKE 前綴不匹配

SELECT * FROM table WHERE name LIKE '%abc';

如果 LIKE 查詢以通配符 % 開頭,索引通常無法被使用,因為 MySQL 無法利用前綴進行快速查找。

8. 如何查看索引

可以通過以下方式查看 MySQL 表的索引信息:

SHOW INDEX FROM table_name;

該語句將列出表 table_name 中所有的索引,包括索引的名稱、類型、涉及的列等信息。

也可以使用explain關鍵字查看一條SQL的執行計劃:

EXPLAIN SELECT * FROM users WHERE age > 30;

結果如下:

idselect_typetabletypepossible_keyskeykey_lenrefrowsExtra
1SIMPLEusersrangeidx_ageidx_age4NULL2Using where

這個執行計劃的解釋為:

  • id: 查詢的唯一標識。這里的 1 表示這是一個簡單查詢。
  • select_type: 查詢的類型。SIMPLE 表示這是一個簡單的查詢(沒有子查詢)。
  • table: 表名。這里查詢的是 users 表。
  • type: 這里的 range 表示 MySQL 使用了范圍掃描(age > 30 是一個范圍條件),這是比 ALL 更高效的掃描類型。
  • possible_keys: MySQL 能夠使用的索引。這里沒有索引可用(NULL)。
  • key: 使用了 idx_age 索引,意味著查詢能夠利用索引進行更高效的檢索。
  • key_len: 使用的索引的長度。
  • ref: 如果使用了索引,它將顯示與哪個列比較。
  • rows: 預估掃描了 2 行,MySQL 使用了索引來減少掃描的行數。
  • Extra: 附加信息。Using where 表示在掃描每一行時,MySQL 使用了 WHERE 子句的條件進行過濾。

9. 索引優化建議

  1. 選擇合適的索引類型:根據查詢的特點選擇合適的索引類型。如果查詢需要精確匹配,可以選擇唯一索引;如果查詢涉及文本搜索,可以選擇全文索引。
  2. 避免過度索引:索引雖然提高查詢效率,但會增加寫操作的開銷。需要在查詢性能和寫操作性能之間做出平衡。
  3. 創建復合索引:對于多個列的查詢,可以考慮創建復合索引,而不是對每個單獨列都創建索引。
  4. 避免索引失效的情況:盡量避免在查詢中使用 LIKEOR!= 等會導致索引失效的操作。
  5. 定期分析和優化索引:通過 EXPLAIN 語句來分析查詢的執行計劃,檢查索引的使用情況,并根據結果調整索引設計。

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

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

相關文章

基于Spring Boot的RabbitMQ延時隊列技術實現

文章目錄 基于Spring Boot的RabbitMQ延時隊列技術實現延時隊列應用場景基本概念實現延時隊列添加依賴基礎配置配置類設計消息生產者消息消費者 兩種TTL設置方式 訂單超時關閉實例訂單服務消息處理 延遲消息插件安裝插件配置延遲交換機 基于Spring Boot的RabbitMQ延時隊列技術實…

畢業項目推薦:基于yolov8/yolov5/yolo11的番茄成熟度檢測識別系統(python+卷積神經網絡)

文章目錄 概要一、整體資源介紹技術要點功能展示&#xff1a;功能1 支持單張圖片識別功能2 支持遍歷文件夾識別功能3 支持識別視頻文件功能4 支持攝像頭識別功能5 支持結果文件導出&#xff08;xls格式&#xff09;功能6 支持切換檢測到的目標查看 二、數據集三、算法介紹1. YO…

【智能客服】ChatGPT大模型話術優化落地方案

本文原創作者:姚瑞南 AI-agent 大模型運營專家,先后任職于美團、獵聘等中大廠AI訓練專家和智能運營專家崗;多年人工智能行業智能產品運營及大模型落地經驗,擁有AI外呼方向國家專利與PMP項目管理證書。(轉載需經授權) 目錄 一、項目背景 1.1 行業背景 1.2 業務現…

STM32的HAL庫開發---單通道ADC采集(DMA讀取)實驗

一、實驗簡介 正常單通道ADC采集順序是先開啟ADC采集&#xff0c;然后等待ADC轉換完成&#xff0c;也就是判斷EOC位置1&#xff0c;然后再讀取數據寄存器的值。 如果配置了DMA功能&#xff0c;在EOC位被硬件置1后&#xff0c;自動產生DMA請求&#xff0c;然后DMA進行數據搬運…

編譯原理基礎(1)

1.什么是ASCII碼&#xff1f; ASCII碼即美國信息交換標準代碼&#xff0c;是基于拉丁字母的電腦編碼系統&#xff0c;用于顯示現代英語和部分西歐語言。其7位編碼范圍0-127&#xff0c;8位擴展到0-255。字符集含控制字符&#xff08;0-31、127&#xff0c;用于控制設備或表示通…

基于 Highcharts 實現 Vue 中的答題統計柱狀圖組件

在現代 Web 開發中&#xff0c;數據可視化是一個重要的組成部分&#xff0c;而 Highcharts 是一個廣泛使用的 JavaScript 圖表庫&#xff0c;可以幫助開發者在 Web 頁面上輕松地繪制豐富的圖表。在本文中&#xff0c;我們將基于 Highcharts 創建一個用于答題統計的柱狀圖&#…

SQLAlchemyError: A transaction is already begun on this Session.

資料 sqlalchemy 事務 - 簡書 在 SQLAlchemy 中&#xff0c;事務是通過會話來管理的。當你開始一個事務&#xff08;例如使用 async with db.begin()&#xff09;&#xff0c;它會開啟一個新的事務&#xff0c;并在事務塊結束時自動提交或回滾。如果在同一個會話中&#xff0c…

Java Web開發實戰與項目——Spring Boot與Redis實現緩存管理

緩存技術在現代Web開發中至關重要&#xff0c;尤其是在高并發的環境中&#xff0c;緩存能夠有效減少數據庫訪問壓力、提高系統性能。Redis作為最流行的內存數據存儲系統之一&#xff0c;常用于緩存管理。本節將講解如何在Spring Boot項目中集成Redis&#xff0c;實現緩存管理&a…

C語言學習【1】C語言關于寄存器的封裝

目錄 1.封裝寄存的C語言的語法volatile&#xff1a;unsigned int:*pGpiobOdrvolatile unsigned int * 2.進一步C語言的封裝 在嵌入式中&#xff0c;底層一定是操作寄存器&#xff0c;我有一個理念&#xff0c;凡事一定要想清楚&#xff0c;把任何知識點融入自己的理解之中&…

#滲透測試#批量漏洞挖掘#暢捷通T+遠程命令執行漏洞

免責聲明 本教程僅為合法的教學目的而準備,嚴禁用于任何形式的違法犯罪活動及其他商業行為,在使用本教程前,您應確保該行為符合當地的法律法規,繼續閱讀即表示您需自行承擔所有操作的后果,如有異議,請立即停止本文章讀。 目錄 一、漏洞概況 二、攻擊特征 三、應急處置…

ollama 學習筆記

1. 參考博客&#xff1a;1. Ollama完整教程&#xff1a;本地LLM管理、WebUI對話、Python/Java客戶端API應用&#xff1a;https://blog.csdn.net/python122_/article/details/1409457202. https://gitee.com/ai-big-model/ollama/tree/main --》REST APIollama 離線安裝包 ollam…

ARM Linux平臺下 OpenCV Camera 實驗

一、硬件原理 1. OV2640 1.1 基本功能 OV2640 是一款低功耗、高性能的圖像傳感器&#xff0c;支持以下功能&#xff1a; 最高分辨率&#xff1a;200 萬像素&#xff08;1600x1200&#xff09;。 輸出格式&#xff1a;JPEG、YUV、RGB。 內置圖像處理功能&#xff1a;自動曝…

vue2.x中父組件通過props向子組件傳遞數據詳細解讀

1. 父組件向子組件傳遞數據的步驟 在子組件中定義 props&#xff1a; 子組件通過 props 選項聲明它期望接收的數據。props 可以是數組形式&#xff08;簡單聲明&#xff09;或對象形式&#xff08;支持類型檢查和默認值&#xff09;。 在父組件中使用子組件時綁定 props&#x…

【Gin】2:快速上手Gin框架(模版、cookie、session)

本文目錄 一、模版渲染二、自定義模版函數三、cookie四、Session五、cookie、session區別六、會話攻擊 一、模版渲染 在 Gin 框架中&#xff0c;模板主要用于動態生成 HTML 頁面&#xff0c;結合 Go 語言的模板引擎功能&#xff0c;實現數據與視圖的分離。 模板渲染是一種動態…

【AI繪畫】大衛? 霍克尼風格——自然的魔法(一丹一世界)

大衛? 霍克尼&#xff0c;很喜歡這個老頭&#xff0c;“藝術是一場戰斗”。老先生零九年有了iphone&#xff0c;開始用iphone畫畫&#xff0c;一零年開始用ipad畫畫&#xff0c;用指頭劃拉&#xff0c;據說五分鐘就能畫一幅&#xff0c;每天早上隨手畫幾幅送給身邊的朋友。很c…

解碼 NLP:從萌芽到蓬勃的技術蛻變之旅

內容概況&#xff1a; 主要講述NLP專欄的內容和NLP的發展及其在現代生活中的廣泛應用。專欄強調實踐為主、理論為輔的學習方法&#xff0c;并通過多個生活場景展示了NLP技術的實際應用&#xff0c;如對話機器人、搜索引擎、翻譯軟件、電商推薦和智能客服等。 這邊我就不多做自我…

解決DeepSeek服務器繁忙問題的實用指南

目錄 簡述 1. 關于服務器繁忙 1.1 服務器負載與資源限制 1.2 會話管理與連接機制 1.3 客戶端配置與網絡問題 2. 關于DeepSeek服務的備用選項 2.1 納米AI搜索 2.2 硅基流動 2.3 秘塔AI搜索 2.4 字節跳動火山引擎 2.5 百度云千帆 2.6 英偉達NIM 2.7 Groq 2.8 Firew…

前端(AJAX)學習筆記(CLASS 2):圖書管理案例以及圖片上傳

* BootStrap彈框 功能&#xff1a;不離開當前頁面&#xff0c;顯示單獨內容&#xff0c;供用戶操作 步驟&#xff1a; 1、引入bootstrap.css和bootstrap.js 2、準備彈框標簽&#xff0c;確認結構 3、通過自定義屬性&#xff0c;控制彈框的顯示和隱藏 其中的bootstrap.css…

數據結構:雙鏈表list

list 是 C 標準庫中的雙向鏈表容器。 list初始化示例&#xff1a; #include <list>int n 7;std::list<int> lst; // 初始化一個空的雙向鏈表 lststd::list<int> lst(n); // 初始化一個大小為 n 的鏈表 lst&#xff0c;鏈表中的值默認都為 0std::list<i…

AI Agent Service Toolkit:一站式大模型智能體開發套件

項目簡介 該工具包基于LangGraph、FastAPI和Streamlit構建,提供了構建和運行大模型Agent的最小原子能力,包含LangGraph代理、FastAPI服務、用于與服務交互的客戶端以及一個使用客戶端提供聊天界面的Streamlit應用。用戶可以利用該工具包提供的模板快速搭建基于LangGraph框架…