最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL?索引從入門到精通示例詳解(核心概念、類型與實(shí)戰(zhàn)優(yōu)化)

 更新時(shí)間:2026年01月14日 09:29:35   作者:heartbeat..  
本文詳細(xì)介紹了MySQL索引的概念、類型及其在實(shí)際應(yīng)用中的優(yōu)化策略,索引可以顯著提升查詢效率,但過(guò)多的索引會(huì)增加寫(xiě)操作的開(kāi)銷,文章涵蓋了索引的創(chuàng)建、維護(hù)和使用技巧,幫助讀者更好地理解和應(yīng)用索引,以優(yōu)化數(shù)據(jù)庫(kù)性能,感興趣的朋友跟隨小編一起看看吧

MySQL 索引從入門到精通:核心概念、類型與實(shí)戰(zhàn)優(yōu)化

一、索引是什么?(核心概念)

可以把索引理解為數(shù)據(jù)庫(kù)表的 “目錄”

沒(méi)有索引時(shí),查詢數(shù)據(jù)需要逐行掃描全表(全表掃描),就像找書(shū)中某段內(nèi)容要逐頁(yè)翻;

有了索引后,數(shù)據(jù)庫(kù)會(huì)先查索引(目錄),快速定位到數(shù)據(jù)所在位置,大幅提升查詢效率。

索引的本質(zhì)是一種排好序的數(shù)據(jù)結(jié)構(gòu)(MySQL 中最常用的是 B+Tree),它存儲(chǔ)了表中一列 / 多列的值,并指向?qū)?yīng)數(shù)據(jù)行的物理地址。

二、MySQL 中常見(jiàn)的索引類型

1. 按 “數(shù)據(jù)結(jié)構(gòu)” 分類(底層實(shí)現(xiàn))

類型特點(diǎn)適用場(chǎng)景
B+Tree 索引MySQL 默認(rèn)索引類型,支持范圍查詢、排序,葉子節(jié)點(diǎn)存儲(chǔ)數(shù)據(jù)地址 / 數(shù)據(jù)本身絕大多數(shù)查詢場(chǎng)景(主鍵、普通字段)
Hash 索引基于哈希表實(shí)現(xiàn),等值查詢極快,但不支持范圍查詢、排序僅 Memory 引擎支持,極少用
全文索引針對(duì)文本內(nèi)容的分詞索引,支持模糊匹配(如 MATCH AGAINST文章、評(píng)論等長(zhǎng)文本檢索

MySQL 官方的索引數(shù)量限制:

限制維度InnoDB 引擎(默認(rèn))MyISAM 引擎
單表總索引數(shù)最多 64 個(gè)(包含所有類型:主鍵、普通、唯一、復(fù)合等)最多 64 個(gè)
單個(gè)復(fù)合索引的字段數(shù)最多 16 個(gè)(比如 idx_abc(a,b,c...) 最多包含 16 個(gè)字段)最多 16 個(gè)
索引字段總長(zhǎng)度最多 3072 字節(jié)(所有索引字段的長(zhǎng)度之和)最多 1000 字節(jié)

補(bǔ)充:MySQL 8.0+ 對(duì)部分限制(如索引長(zhǎng)度)有小幅放寬,但 “單表 64 個(gè)索引” 是通用上限,且?guī)缀醪粫?huì)用到。

中小型表(數(shù)據(jù)量 ≤ 100 萬(wàn)):控制在 5~8 個(gè) 以內(nèi);

大型表(100 萬(wàn) < 數(shù)據(jù)量 ≤ 1000 萬(wàn)):控制在 8~12 個(gè) 以內(nèi);

超大型表(數(shù)據(jù)量 > 1000 萬(wàn)):建議不超過(guò) 15 個(gè),且優(yōu)先用 “復(fù)合索引” 替代多個(gè)單字段索引(比如用 idx_age_gender(age, gender) 替代 idx_age + idx_gender)。

2. 按 “功能 / 創(chuàng)建方式” 分類(實(shí)際開(kāi)發(fā)常用)

(1)主鍵索引(PRIMARY KEY)

特殊的唯一索引,一張表只能有一個(gè)主鍵索引;

主鍵字段值不能為 NULL,且必須唯一;

-- 創(chuàng)建表時(shí)指定主鍵索引
CREATE TABLE user (
    id INT NOT NULL,
    name VARCHAR(20),
    PRIMARY KEY (id)  -- 主鍵索引(底層是B+Tree)
);

(2)唯一索引(UNIQUE)

保證索引字段的值唯一,但允許 NULL(多個(gè) NULL 不沖突);

一張表可以有多個(gè)唯一索引;

-- 給user表的phone字段加唯一索引
CREATE UNIQUE INDEX idx_user_phone ON user (phone);

(3)普通索引(INDEX)

最基礎(chǔ)的索引,無(wú)唯一性、非空限制,僅用于提升查詢速度;

-- 給user表的name字段加普通索引
CREATE INDEX idx_user_name ON user (name);

(4)復(fù)合索引(聯(lián)合索引)

基于多個(gè)字段創(chuàng)建的索引,遵循 “最左前綴原則”;

-- 給user表的age+gender創(chuàng)建復(fù)合索引
CREATE INDEX idx_user_age_gender ON user (age, gender);
-- 最左前綴原則:能命中索引的查詢是 age / age+gender,僅查 gender 則不命中

補(bǔ):左前原則:就是“最左前綴原則”

當(dāng)你創(chuàng)建復(fù)合索引(比如 idx_age_gender(age, gender))時(shí),MySQL 會(huì)優(yōu)先匹配索引中最左側(cè)的字段,然后依次向右匹配 —— 只有查詢條件包含 “最左前綴”,才能命中該復(fù)合索引;跳過(guò)左側(cè)字段直接查右側(cè)字段,索引會(huì)失效。

簡(jiǎn)單說(shuō):復(fù)合索引 (a, b, c) 的有效匹配順序是 aa+ba+b+c,而 b、c、b+c 都無(wú)法命中該索引。

舉個(gè)例子:

表結(jié)構(gòu)為

CREATE TABLE user (
    id INT PRIMARY KEY,
    age INT,
    gender VARCHAR(2),
    city VARCHAR(20)
);
-- 創(chuàng)建復(fù)合索引:age(左1)→ gender(左2)→ city(左3)
CREATE INDEX idx_age_gender_city ON user (age, gender, city);

樣例:

特殊情況:字段順序不影響(只要包含最左前綴)

MySQL 會(huì)自動(dòng)優(yōu)化查詢條件的字段順序,只要包含最左前綴,即使順序打亂也能命中:

-- 條件字段順序是 gender + age,但包含最左前綴 age → 仍命中索引
SELECT * FROM user WHERE gender = '男' AND age = 20;

底層原因:

復(fù)合索引的 B+Tree 結(jié)構(gòu)是先按左 1 字段排序,再按左 2 字段排序,最后按左 3 字段排序

葉子節(jié)點(diǎn)先按 age 從小到大排,age 相同的再按 gender 排,gender 相同的再按 city 排;

如果沒(méi)有 age 這個(gè) “排序依據(jù)”,數(shù)據(jù)庫(kù)無(wú)法在索引樹(shù)中定位到 gendercity 的數(shù)據(jù),只能全表掃描。

避坑:

不要跳過(guò)左側(cè)字段:比如復(fù)合索引 (a,b),別只查 b,要么加 a,要么給 b 單獨(dú)建索引;

合理設(shè)計(jì)復(fù)合索引字段順序:把查詢頻率最高、區(qū)分度最高的字段放在最左側(cè)(比如 agegender 區(qū)分度高,放左 1);

范圍查詢會(huì)中斷后續(xù)匹配:如果左 1 字段用 >/</BETWEEN 等范圍查詢,右側(cè)字段無(wú)法命中索引:

-- age 用范圍查詢,gender 無(wú)法命中索引(僅 age 部分生效)
SELECT * FROM user WHERE age > 20 AND gender = '男';

(5)前綴索引

針對(duì)字符串字段(如 VARCHAR、TEXT),僅對(duì)字段的前 N 個(gè)字符創(chuàng)建索引,節(jié)省存儲(chǔ)空間;

示例:

-- 給address字段的前10個(gè)字符創(chuàng)建前綴索引
CREATE INDEX idx_user_address ON user (address(10));

三、索引的優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

大幅提升查詢效率(尤其是大數(shù)據(jù)量表);

加速排序、分組操作(ORDER BY/GROUP BY);

約束數(shù)據(jù)唯一性(主鍵 / 唯一索引)。

缺點(diǎn)

增加寫(xiě)操作開(kāi)銷(INSERT/UPDATE/DELETE 時(shí),需要同步更新索引,耗時(shí)更長(zhǎng));

占用額外存儲(chǔ)空間(索引文件會(huì)占用磁盤空間);

索引創(chuàng)建 / 維護(hù)需要成本(過(guò)多索引會(huì)拖慢數(shù)據(jù)庫(kù)整體性能)。

四、索引使用

適合加索引的場(chǎng)景:

查詢頻繁的字段(如 WHERE 條件、JOIN 關(guān)聯(lián)字段);

主鍵、唯一約束字段(必須加);

排序 / 分組字段(ORDER BY/GROUP BY)。

不適合加索引的場(chǎng)景:

數(shù)據(jù)量極小的表(全表掃描比查索引更快);

頻繁更新的字段(寫(xiě)操作會(huì)頻繁更新索引);

低基數(shù)字段(如性別(男 / 女),區(qū)分度太低,索引效果差);

NULL 值占比極高的字段。

避坑要點(diǎn):

遵循復(fù)合索引的 “最左前綴原則”;

避免索引失效(如 WHERE 中用函數(shù)操作索引字段:WHERE DATE(create_time) = '2026-01-13');

不要?jiǎng)?chuàng)建過(guò)多索引(一張表建議控制在 5-8 個(gè)以內(nèi))。

五、InnoDB引擎中的索引

這個(gè)時(shí)候就有老鐵要問(wèn)了,為什么要單獨(dú)拎出來(lái)講解InnoDB引擎的索引,

因?yàn)镮nnoDB 是 MySQL 默認(rèn)且最常用的引擎,其索引設(shè)計(jì)(聚簇索引 + 二級(jí)索引)與 MyISAM 等其他引擎有本質(zhì)區(qū)別,是可以幫助我們理解 MySQL 索引工作原理。

1、一級(jí)索引和二級(jí)索引

一級(jí)索引和二級(jí)索引是針對(duì) InnoDB 引擎的索引分類方式(MyISAM 無(wú)此劃分),核心區(qū)別是索引葉子節(jié)點(diǎn)存儲(chǔ)的內(nèi)容和在查詢中的作用:

一級(jí)索引(Primary Index):就是聚簇索引,是 InnoDB 表的 “主索引”,葉子節(jié)點(diǎn)直接存儲(chǔ)完整的行數(shù)據(jù);

二級(jí)索引(Secondary Index):也叫 “輔助索引”,包括普通索引、唯一索引、復(fù)合索引、全文索引等所有非聚簇索引,葉子節(jié)點(diǎn)僅存儲(chǔ) “索引字段值 + 主鍵值”,不存儲(chǔ)完整行數(shù)據(jù)。

差異:

特征一級(jí)索引(聚簇索引)二級(jí)索引(輔助索引)
本質(zhì)聚簇索引非聚簇索引(普通 / 唯一 / 復(fù)合 / 全文等)
葉子節(jié)點(diǎn)內(nèi)容完整的行數(shù)據(jù)索引字段值 + 主鍵值
表中數(shù)量只能有 1 個(gè)可以有多個(gè)
查詢是否需回表無(wú)需回表(直接拿數(shù)據(jù))查完整數(shù)據(jù)需回表(通過(guò)主鍵查一級(jí)索引)
默認(rèn)創(chuàng)建主鍵自動(dòng)作為一級(jí)索引需手動(dòng)創(chuàng)建(除隱式主鍵外)

(1)一級(jí)索引(聚簇索引):

一級(jí)索引的創(chuàng)建規(guī)則

InnoDB 會(huì)按優(yōu)先級(jí)自動(dòng)確定一級(jí)索引:

優(yōu)先使用用戶定義的 PRIMARY KEY(主鍵)作為一級(jí)索引;

若無(wú)主鍵,找第一個(gè) “非空唯一索引(UNIQUE NOT NULL)” 作為一級(jí)索引;

若以上都沒(méi)有,InnoDB 會(huì)隱式創(chuàng)建一個(gè) 6 字節(jié)的自增整型列(GEN_CLUST_INDEX)作為一級(jí)索引。

一級(jí)索引的查詢邏輯

因?yàn)槿~子節(jié)點(diǎn)直接存完整行數(shù)據(jù),所以通過(guò)一級(jí)索引查詢時(shí),一步就能拿到所有需要的字段,無(wú)需任何額外操作。

示例(基于之前的 user 表,id 是主鍵 / 一級(jí)索引):

-- 用一級(jí)索引(id)查詢,直接從葉子節(jié)點(diǎn)拿數(shù)據(jù),無(wú)回表
SELECT * FROM user WHERE id = 10;

(2)二級(jí)索引(輔助索引)

二級(jí)索引的類型

所有手動(dòng)創(chuàng)建的非主鍵索引都屬于二級(jí)索引,比如:

-- 普通索引(二級(jí)索引)
CREATE INDEX idx_user_name ON user (name);
-- 唯一索引(二級(jí)索引)
CREATE UNIQUE INDEX idx_user_phone ON user (phone);
-- 復(fù)合索引(二級(jí)索引)
CREATE INDEX idx_user_age_gender ON user (age, gender);
-- 全文索引(二級(jí)索引)
FULLTEXT INDEX idx_article_content ON article (content);

二級(jí)索引的查詢邏輯

二級(jí)索引的葉子節(jié)點(diǎn)只有 “索引字段 + 主鍵”,所以查詢時(shí)分為兩種情況:

覆蓋索引場(chǎng)景:查詢字段僅包含 “索引字段 + 主鍵”→ 直接從二級(jí)索引拿數(shù)據(jù),無(wú)需回表;

非覆蓋場(chǎng)景:查詢字段包含其他列 → 先查二級(jí)索引拿到主鍵,再用主鍵查一級(jí)索引(回表)。

示例 1(覆蓋索引,無(wú)回表):

-- 查詢字段:name(索引字段) + id(主鍵),都在二級(jí)索引葉子節(jié)點(diǎn)
SELECT id, name FROM user WHERE name = '張三';

示例 2(非覆蓋場(chǎng)景,需回表):

-- 查詢字段包含age(不在idx_user_name葉子節(jié)點(diǎn)),需回表查一級(jí)索引
SELECT id, name, age FROM user WHERE name = '張三';

(3)一級(jí) / 二級(jí)索引的關(guān)聯(lián)(查詢流程示例)

為了讓你更直觀理解,我們拆解一個(gè)完整的二級(jí)索引查詢流程:

假設(shè) user 表中 id=10 的用戶 name='張三'、age=25,執(zhí)行 SELECT age FROM user WHERE name = '張三'

數(shù)據(jù)庫(kù)先檢索二級(jí)索引 idx_user_name,找到 name='張三' 對(duì)應(yīng)的主鍵值 id=10;

再用 id=10 檢索一級(jí)索引(聚簇索引),從葉子節(jié)點(diǎn)中拿到 age=25;

返回結(jié)果給用戶。

這個(gè)過(guò)程中,第二步就是 “回表”,本質(zhì)是二級(jí)索引依賴一級(jí)索引才能獲取完整數(shù)據(jù)

2、聚簇索引:

(1)聚簇索引是什么?

聚簇索引(Clustered Index)可以理解為:索引的葉子節(jié)點(diǎn)直接存儲(chǔ)了整張表的行數(shù)據(jù),而非僅僅存儲(chǔ)指向數(shù)據(jù)的指針。

打個(gè)更形象的比方:

普通索引(非聚簇索引)像書(shū)籍的 “目錄”,目錄里只寫(xiě)了 “某章節(jié)在第 XX 頁(yè)”,需要先查目錄,再翻到對(duì)應(yīng)頁(yè)碼找內(nèi)容;

聚簇索引則像書(shū)籍本身就是 “按目錄排序的”—— 目錄和內(nèi)容合二為一,目錄的最后一頁(yè)就是內(nèi)容的對(duì)應(yīng)頁(yè),不需要二次查找。

注意:MySQL 的 InnoDB 引擎才支持聚簇索引,MyISAM 引擎沒(méi)有聚簇索引的概念(MyISAM 所有索引都是非聚簇的)。

(2)聚簇索引的特點(diǎn)

一張表只能有一個(gè)聚簇索引

因?yàn)榫鄞厮饕娜~子節(jié)點(diǎn)就是數(shù)據(jù)本身,數(shù)據(jù)行只能以一種物理順序存儲(chǔ),所以 InnoDB 表最多只能有一個(gè)聚簇索引。

主鍵就是默認(rèn)的聚簇索引

InnoDB 會(huì)優(yōu)先將主鍵索引作為聚簇索引:

如果你給表定義了主鍵(PRIMARY KEY),InnoDB 就以這個(gè)主鍵創(chuàng)建聚簇索引;

如果你沒(méi)定義主鍵,InnoDB 會(huì)找第一個(gè)非空唯一索引作為聚簇索引;

如果連非空唯一索引都沒(méi)有,InnoDB 會(huì)隱式創(chuàng)建一個(gè)名為 GEN_CLUST_INDEX 的自增 6 字節(jié)整型列作為聚簇索引。

聚簇索引的結(jié)構(gòu)(B+Tree)

以主鍵為聚簇索引的結(jié)構(gòu)如下:

                根節(jié)點(diǎn)(主鍵范圍)
               /        \
        分支節(jié)點(diǎn)1      分支節(jié)點(diǎn)2
       /    \         /    \
  葉子節(jié)點(diǎn)1  葉子節(jié)點(diǎn)2 葉子節(jié)點(diǎn)3  葉子節(jié)點(diǎn)4
  (存儲(chǔ)完整行數(shù)據(jù))  (存儲(chǔ)完整行數(shù)據(jù))

非葉子節(jié)點(diǎn):存儲(chǔ)主鍵值和指向子節(jié)點(diǎn)的指針;

葉子節(jié)點(diǎn):按主鍵順序存儲(chǔ)完整的行數(shù)據(jù),且葉子節(jié)點(diǎn)之間通過(guò)雙向鏈表連接(方便范圍查詢)。

非聚簇索引(二級(jí)索引)依賴聚簇索引

InnoDB 中所有的普通索引、唯一索引、復(fù)合索引等,都屬于 “二級(jí)索引”,它們的葉子節(jié)點(diǎn)只存儲(chǔ)索引字段值 + 主鍵值,而非完整行數(shù)據(jù)。

舉個(gè)例子:

假設(shè)有 user 表,主鍵是 id(聚簇索引),給 name 加了普通索引(二級(jí)索引):

CREATE TABLE user (
    id INT PRIMARY KEY,  -- 聚簇索引
    name VARCHAR(20),
    age INT
);
CREATE INDEX idx_user_name ON user (name);  -- 二級(jí)索引

當(dāng)執(zhí)行 SELECT * FROM user WHERE name = '張三' 時(shí),InnoDB 會(huì)做兩步操作:

  1. 先查 idx_user_name 這個(gè)二級(jí)索引,找到 name='張三' 對(duì)應(yīng)的主鍵值(比如 id=10);
  2. 再用這個(gè)主鍵值查聚簇索引,找到 id=10 對(duì)應(yīng)的完整行數(shù)據(jù)(回表查詢)。
(3)聚簇索引的優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

查詢效率極高:主鍵查詢時(shí),直接從聚簇索引的葉子節(jié)點(diǎn)拿到完整數(shù)據(jù),無(wú)需回表;

范圍查詢快:葉子節(jié)點(diǎn)是有序的雙向鏈表,按主鍵范圍查詢(如 id BETWEEN 10 AND 20)時(shí),只需遍歷鏈表即可;

數(shù)據(jù)物理存儲(chǔ)有序:行數(shù)據(jù)按主鍵物理排序,減少磁盤 I/O。

缺點(diǎn)

插入速度受主鍵順序影響大:

如果主鍵是自增整型(如 id INT AUTO_INCREMENT),新數(shù)據(jù)會(huì)追加到葉子節(jié)點(diǎn)末尾,插入效率高;

如果主鍵是無(wú)序值(如 UUID),插入時(shí)需要移動(dòng)數(shù)據(jù)來(lái)維持有序性,會(huì)導(dǎo)致大量磁盤 I/O,性能下降。

更新主鍵代價(jià)高:更新主鍵會(huì)改變數(shù)據(jù)的物理存儲(chǔ)位置,同時(shí)所有二級(jí)索引的主鍵值也需要同步更新;

頁(yè)分裂問(wèn)題:當(dāng)一個(gè)葉子節(jié)點(diǎn)存滿數(shù)據(jù),插入新數(shù)據(jù)時(shí)會(huì)觸發(fā)頁(yè)分裂,增加額外開(kāi)銷。

(4)四聚簇索引 vs 非聚簇索引(核心區(qū)別)
維度聚簇索引(InnoDB 主鍵)非聚簇索引(二級(jí)索引 / MyISAM 索引)
葉子節(jié)點(diǎn)存儲(chǔ)內(nèi)容完整的行數(shù)據(jù)索引字段值 + 指向數(shù)據(jù)的指針(InnoDB 是主鍵值,MyISAM 是物理地址)
表中數(shù)量只能有 1 個(gè)可以有多個(gè)
查詢是否需要回表主鍵查詢無(wú)需回表查完整數(shù)據(jù)需要回表(InnoDB)
數(shù)據(jù)物理順序按索引順序存儲(chǔ)數(shù)據(jù)物理存儲(chǔ)與索引無(wú)關(guān)

3、什么是回表?

(1)先明確:什么是回表?

回表是 InnoDB 引擎特有的操作,本質(zhì)是:

當(dāng)你通過(guò)非聚簇索引(二級(jí)索引,如普通索引、唯一索引) 查詢數(shù)據(jù)時(shí),如果需要的字段不在該二級(jí)索引的葉子節(jié)點(diǎn)中,數(shù)據(jù)庫(kù)會(huì)先查二級(jí)索引拿到主鍵值,再用主鍵值去聚簇索引中查找完整行數(shù)據(jù)的過(guò)程。

簡(jiǎn)單說(shuō):回表 = 查二級(jí)索引(拿主鍵) + 查聚簇索引(拿完整數(shù)據(jù)),是兩次索引查詢的組合。

(2)回表發(fā)生的核心條件

回表的發(fā)生需要同時(shí)滿足兩個(gè)條件:

  1. 查詢依賴的是二級(jí)索引(不是聚簇索引);
  2. 查詢需要的字段不全在二級(jí)索引的葉子節(jié)點(diǎn)中(葉子節(jié)點(diǎn)只有 “索引字段 + 主鍵”)。
(3)回表發(fā)生的具體場(chǎng)景(附示例)

以下所有示例均基于這個(gè)表結(jié)構(gòu)(InnoDB 引擎):

CREATE TABLE user (
    id INT PRIMARY KEY,  -- 聚簇索引(葉子節(jié)點(diǎn)存完整行數(shù)據(jù))
    name VARCHAR(20),
    age INT,
    gender VARCHAR(2),
    phone VARCHAR(11)
);
-- 創(chuàng)建二級(jí)索引:普通索引
CREATE INDEX idx_user_name ON user (name);  -- 葉子節(jié)點(diǎn):name + id
CREATE INDEX idx_user_age_gender ON user (age, gender);  -- 葉子節(jié)點(diǎn):age + gender + id

場(chǎng)景 1:查詢字段包含非索引字段(最常見(jiàn))

-- 條件用二級(jí)索引字段name,但查詢字段包含age(不在idx_user_name的葉子節(jié)點(diǎn))
SELECT id, name, age FROM user WHERE name = '張三';

第一步:查 idx_user_name 二級(jí)索引,找到 name='張三' 對(duì)應(yīng)的主鍵 id;

第二步:用 id 查聚簇索引,拿到 age 字段 → 觸發(fā)回表。

場(chǎng)景 2:查詢 *(所有字段)且條件用二級(jí)索引

-- 查詢所有字段,條件用二級(jí)索引字段age
SELECT * FROM user WHERE age = 20;

* 包含 phone 等不在 idx_user_age_gender 葉子節(jié)點(diǎn)的字段,必須回表查聚簇索引才能拿到完整數(shù)據(jù) → 觸發(fā)回表。

場(chǎng)景 3:復(fù)合索引不滿足 “覆蓋”,需額外字段

-- 條件用復(fù)合索引的age,但查詢字段包含phone(不在索引中)
SELECT id, age, phone FROM user WHERE age = 20;

復(fù)合索引 idx_user_age_gender 的葉子節(jié)點(diǎn)只有 age + gender + id,沒(méi)有 phone → 觸發(fā)回表。

(4)不會(huì)發(fā)生回表的場(chǎng)景(對(duì)比理解)

場(chǎng)景 1:直接用聚簇索引(主鍵)查詢

-- 條件用主鍵(聚簇索引),無(wú)論查什么字段都不回表
SELECT * FROM user WHERE id = 10;

聚簇索引的葉子節(jié)點(diǎn)直接存完整行數(shù)據(jù),一步就能拿到所有字段 → 無(wú)回表。

場(chǎng)景 2:查詢字段僅包含 “二級(jí)索引字段 + 主鍵”(覆蓋索引)

-- 查詢字段:name(索引字段) + id(主鍵),都在idx_user_name的葉子節(jié)點(diǎn)
SELECT id, name FROM user WHERE name = '張三';

無(wú)需查聚簇索引,直接從二級(jí)索引拿到所有需要的字段 → 無(wú)回表(這就是 “覆蓋索引” 的核心價(jià)值)。

場(chǎng)景 3:復(fù)合索引覆蓋所有查詢字段

-- 查詢字段:age + gender + id,都在idx_user_age_gender的葉子節(jié)點(diǎn)
SELECT id, age, gender FROM user WHERE age = 20;

復(fù)合索引的葉子節(jié)點(diǎn)包含所有查詢字段 → 無(wú)回表。

(5)如何避免回表?(實(shí)用優(yōu)化方案)

回表會(huì)增加一次索引查詢,大數(shù)據(jù)量下會(huì)顯著降低性能,可通過(guò)以下方式避免:

使用覆蓋索引(最推薦):

調(diào)整查詢語(yǔ)句,只查 “二級(jí)索引字段 + 主鍵”,不查額外字段;

或創(chuàng)建包含所需字段的復(fù)合索引(比如將常用查詢字段加入復(fù)合索引):

-- 原查詢需要name + age,給name和age建復(fù)合索引
CREATE INDEX idx_user_name_age ON user (name, age);
-- 此時(shí)查詢 SELECT id, name, age FROM user WHERE name = '張三' 無(wú)需回表

優(yōu)先用主鍵查詢:如果業(yè)務(wù)允許,先通過(guò)其他方式拿到主鍵,再用主鍵查數(shù)據(jù)(比如先查 name 拿到 id,再用 id 查 *)。

合理設(shè)計(jì)索引:將高頻查詢的字段加入復(fù)合索引,讓索引覆蓋更多查詢場(chǎng)景。

總結(jié)

索引是 MySQL 提升查詢效率的核心手段,本質(zhì)是 “有序數(shù)據(jù)結(jié)構(gòu)(B+Tree 為主)”,可類比為 “表的目錄”;

常用索引類型包括主鍵索引、唯一索引、普通索引、復(fù)合索引,其中復(fù)合索引需遵循 “最左前綴原則”;

,大數(shù)據(jù)量下會(huì)顯著降低性能,可通過(guò)以下方式避免:

使用覆蓋索引(最推薦):

調(diào)整查詢語(yǔ)句,只查 “二級(jí)索引字段 + 主鍵”,不查額外字段;

或創(chuàng)建包含所需字段的復(fù)合索引(比如將常用查詢字段加入復(fù)合索引):

-- 原查詢需要name + age,給name和age建復(fù)合索引
CREATE INDEX idx_user_name_age ON user (name, age);
-- 此時(shí)查詢 SELECT id, name, age FROM user WHERE name = '張三' 無(wú)需回表

優(yōu)先用主鍵查詢:如果業(yè)務(wù)允許,先通過(guò)其他方式拿到主鍵,再用主鍵查數(shù)據(jù)(比如先查 name 拿到 id,再用 id 查 *)。

合理設(shè)計(jì)索引:將高頻查詢的字段加入復(fù)合索引,讓索引覆蓋更多查詢場(chǎng)景。

總結(jié)

索引是 MySQL 提升查詢效率的核心手段,本質(zhì)是 “有序數(shù)據(jù)結(jié)構(gòu)(B+Tree 為主)”,可類比為 “表的目錄”;

常用索引類型包括主鍵索引、唯一索引、普通索引、復(fù)合索引,其中復(fù)合索引需遵循 “最左前綴原則”;

索引并非越多越好,要平衡查詢效率和寫(xiě)操作開(kāi)銷,僅給高頻查詢、低更新的字段加索引。

到此這篇關(guān)于MySQL 索引從入門到精通示例詳解(核心概念、類型與實(shí)戰(zhàn)優(yōu)化)的文章就介紹到這了,更多相關(guān)mysql索引類型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL在Windows上安裝的詳細(xì)流程

    MySQL在Windows上安裝的詳細(xì)流程

    MySQL 是最流行的數(shù)據(jù)庫(kù)管理系統(tǒng) (DBMS) 之一,它輕量、開(kāi)源且易于安裝和使用,因此對(duì)于那些剛開(kāi)始學(xué)習(xí)和使用關(guān)系數(shù)據(jù)庫(kù)的人來(lái)說(shuō)是一個(gè)不錯(cuò)的選擇, 本文主要系統(tǒng)介紹Windows的環(huán)境下MySQL的安裝過(guò)程和驗(yàn)證過(guò)程,需要的朋友可以參考下
    2024-12-12
  • MYSQL row_number()與over()函數(shù)用法詳解

    MYSQL row_number()與over()函數(shù)用法詳解

    這篇文章主要介紹了MYSQL row_number()與over()函數(shù)用法詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Mysql prepare預(yù)處理的具體使用

    Mysql prepare預(yù)處理的具體使用

    本文主要介紹了Mysql prepare預(yù)處理,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • mysql利用mysqlbinlog命令恢復(fù)誤刪除數(shù)據(jù)的實(shí)現(xiàn)

    mysql利用mysqlbinlog命令恢復(fù)誤刪除數(shù)據(jù)的實(shí)現(xiàn)

    這篇文章主要介紹了mysql利用mysqlbinlog命令恢復(fù)誤刪除數(shù)據(jù)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • MySQL擴(kuò)展VARCHAR長(zhǎng)度遭遇問(wèn)題匯總分析

    MySQL擴(kuò)展VARCHAR長(zhǎng)度遭遇問(wèn)題匯總分析

    這篇文章主要為大家介紹了MySQL擴(kuò)展VARCHAR長(zhǎng)度遭遇問(wèn)題匯總分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-02-02
  • mysql8.0.14.zip安裝時(shí)自動(dòng)創(chuàng)建data文件夾失敗服務(wù)無(wú)法啟動(dòng)

    mysql8.0.14.zip安裝時(shí)自動(dòng)創(chuàng)建data文件夾失敗服務(wù)無(wú)法啟動(dòng)

    這篇文章主要介紹了mysql8.0.14.zip安裝時(shí)自動(dòng)創(chuàng)建data文件夾失敗,導(dǎo)致服務(wù)無(wú)法啟動(dòng)的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • 通過(guò)SQL語(yǔ)句來(lái)備份,還原數(shù)據(jù)庫(kù)

    通過(guò)SQL語(yǔ)句來(lái)備份,還原數(shù)據(jù)庫(kù)

    這里僅僅用到了一種方式而已,把數(shù)據(jù)庫(kù)文件備份到磁盤然后在恢復(fù).
    2010-02-02
  • 阿里云centos7安裝mysql8.0.22的詳細(xì)教程

    阿里云centos7安裝mysql8.0.22的詳細(xì)教程

    這篇文章主要介紹了阿里云centos7安裝mysql8.0.22的詳細(xì)教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • MySQL使用EXPLAIN分析SQL語(yǔ)句的完整指南

    MySQL使用EXPLAIN分析SQL語(yǔ)句的完整指南

    在數(shù)據(jù)庫(kù)性能調(diào)優(yōu)中,EXPLAIN是MySQL提供的核心工具之一,本文將結(jié)合真實(shí)案例與官方文檔,系統(tǒng)講解EXPLAIN的使用方法及優(yōu)化策略,有需要的可以了解下
    2026-02-02
  • Debian中完全卸載MySQL的方法

    Debian中完全卸載MySQL的方法

    這篇文章主要介紹了Debian中完全卸載MySQL的方法,同時(shí)介紹了清理方法,可以做到徹底卸載mysql,需要的朋友可以參考下
    2014-06-06

最新評(píng)論

富源县| 甘孜县| 峡江县| 贵溪市| 镇原县| 桓仁| 灵丘县| 霍林郭勒市| 江北区| 宝鸡市| 扎囊县| 保山市| 洛宁县| 四子王旗| 定襄县| 宜川县| 高青县| 颍上县| 徐州市| 全州县| 海安县| 施秉县| 武胜县| 金溪县| 青浦区| 河西区| 远安县| 抚宁县| 乐陵市| 湘西| 仁布县| 会宁县| 伊吾县| 湖州市| 和静县| 依安县| 陇南市| 临朐县| 三河市| 聊城市| 禹城市|