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

MySQL聯(lián)合索引設(shè)計(jì)中字段順序、區(qū)分度與優(yōu)化器行為示例詳解

 更新時(shí)間:2025年11月13日 11:05:31   作者:代碼怪獸大大作戰(zhàn)  
索引設(shè)計(jì)是數(shù)據(jù)庫(kù)優(yōu)化中的關(guān)鍵環(huán)節(jié),遵循三大黃金原則可顯著提升查詢(xún)性能,這篇文章主要介紹了MySQL聯(lián)合索引設(shè)計(jì)中字段順序、區(qū)分度與優(yōu)化器行為的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下,

在日常開(kāi)發(fā)中,我們常常為查詢(xún)加上聯(lián)合索引,例如:

CREATE INDEX idx_unit_user ON t_user (unit_id, user_id);

但在很多項(xiàng)目里,還能看到這種寫(xiě)法:

CREATE INDEX idx_del_unit_user ON t_user (del_flag, unit_id, user_id);

del_flag 表示是否刪除,只有 01 兩種取值。

很多人認(rèn)為“查詢(xún)總有 del_flag=0 條件,索引當(dāng)然要從它開(kāi)始”,

但事實(shí)上,這樣反而可能拖慢查詢(xún)速度。

本文將系統(tǒng)講清楚三個(gè)關(guān)鍵問(wèn)題

  1. 聯(lián)合索引字段順序的重要性

  2. 區(qū)分度(Cardinality)對(duì)索引效率的影響

  3. MySQL 優(yōu)化器是否會(huì)自動(dòng)調(diào)整 WHERE 條件順序

一、聯(lián)合索引的匹配原理回顧

聯(lián)合索引 (a, b, c) 的底層是一個(gè) B+Tree

MySQL 檢索時(shí)會(huì)按照索引定義的列順序有序排列:

a → b → c

因此,它遵循 最左前綴原則(Leftmost Prefix Rule)

  • 可以命中 (a)(a,b)、(a,b,c);

  • 但無(wú)法單獨(dú)命中 (b)、(c)(b,c)。

這意味著:索引列的順序決定了 MySQL 能否利用該索引。

二、區(qū)分度(Cardinality)是什么?

區(qū)分度是衡量字段“區(qū)分能力”的指標(biāo):

區(qū)分度 = 不同值數(shù)量 / 總記錄數(shù)

可通過(guò)命令查看:

SHOW INDEX FROM your_table;

其中 Cardinality 表示索引中不同值的大致數(shù)量。

字段取值示例區(qū)分度是否適合放在索引前面
del_flag0/1極低?
genderM/F極低?
unit_id上千單位中高?
user_id唯一極高?

三、為什么低區(qū)分度字段放前面會(huì)拖慢查詢(xún)?

假設(shè)你定義了:

CREATE INDEX idx_del_unit_user ON t_user (del_flag, unit_id, user_id);

del_flag 只有兩種值(0、1)。

查詢(xún)?nèi)缦拢?/p>

SELECT * FROM t_user WHERE del_flag = 0 AND unit_id = 1001;

索引的邏輯結(jié)構(gòu)類(lèi)似:

(del_flag=0) → [unit_id 排序 ...]

(del_flag=1) → [unit_id 排序 ...]

MySQL 實(shí)際上會(huì)掃描整個(gè) (del_flag=0) 這半邊索引樹(shù),

再在其中過(guò)濾出 unit_id=1001 的數(shù)據(jù)。

因?yàn)?del_flag 不能有效縮小數(shù)據(jù)范圍,性能幾乎無(wú)提升。

低區(qū)分度列放在前面時(shí),索引分區(qū)極不均衡,效果有限。

四、優(yōu)化設(shè)計(jì):高區(qū)分度字段放前

如果查詢(xún)模式是:

WHERE del_flag=0 AND unit_id=? AND user_id=?

更合理的索引應(yīng)為:

CREATE INDEX idx_unit_user_del ON t_user (unit_id, user_id, del_flag);

執(zhí)行順序如下:

  1. MySQL 先根據(jù) unit_id 定位;

  2. 再通過(guò) user_id 精確匹配;

  3. 最后判斷 del_flag=0。

結(jié)果是:掃描范圍更小,性能顯著提升。

五、WHERE 條件順序會(huì)影響嗎?

很多人問(wèn):

“如果我寫(xiě)的 SQL 是 WHERE del_flag=0 AND unit_id=? AND user_id=?,
那是不是應(yīng)該把 unit_id 放前面?”

答案是:不用。

MySQL 優(yōu)化器會(huì)自動(dòng)調(diào)整邏輯順序

MySQL 的優(yōu)化器會(huì):

  • 自動(dòng)重排 WHERE 條件;

  • 根據(jù)各條件的“選擇性”(區(qū)分度)判斷最優(yōu)的索引路徑;

  • 但它不會(huì)改變索引的定義順序。

換句話說(shuō):

  • 寫(xiě) SQL 的順序不重要;

  • 索引定義的順序才重要。

實(shí)測(cè)驗(yàn)證

索引:

CREATE INDEX idx_unit_user_del ON t_user (unit_id, user_id, del_flag);

兩條 SQL:

EXPLAIN SELECT * FROM t_user 
WHERE del_flag=0 AND unit_id=1001 AND user_id=8888;

EXPLAIN SELECT * FROM t_user 
WHERE unit_id=1001 AND user_id=8888 AND del_flag=0;

結(jié)果完全一致:

key: idx_unit_user_del
key_len: ...
rows: 1
Extra: Using index condition

? 說(shuō)明優(yōu)化器自動(dòng)識(shí)別了最優(yōu)執(zhí)行路徑,
WHERE 條件順序無(wú)關(guān)緊要。

但優(yōu)化器不會(huì)“反轉(zhuǎn)索引”

如果索引定義是:

CREATE INDEX idx_del_unit_user ON t_user (del_flag, unit_id, user_id);

那無(wú)論你寫(xiě):

WHERE unit_id=1001 AND user_id=8888 AND del_flag=0;

還是反過(guò)來(lái)寫(xiě),

優(yōu)化器都無(wú)法跳過(guò) del_flag 直接用 (unit_id, user_id)

只能從 del_flag=0 那個(gè)分支掃描,性能依然很差。

六、實(shí)戰(zhàn)對(duì)比

查詢(xún)索引是否命中說(shuō)明
WHERE unit_id=? AND user_id=? AND del_flag=0(unit_id, user_id, del_flag)? 完整命中?? 性能最優(yōu)
WHERE del_flag=0 AND unit_id=? AND user_id=?(unit_id, user_id, del_flag)? 完整命中?? 一樣快
WHERE del_flag=0 AND unit_id=?(unit_id, user_id, del_flag)? 部分命中?? 仍快
WHERE del_flag=0(unit_id, user_id, del_flag)? 不命中最左前綴?? 慢
WHERE unit_id=? AND user_id=?(del_flag, unit_id, user_id)? 無(wú)法跳過(guò) del_flag?? 慢

七、區(qū)分度與索引順序的設(shè)計(jì)原則

原則說(shuō)明
區(qū)分度優(yōu)先高區(qū)分度列放在前(如 unit_id、user_id)
過(guò)濾性?xún)?yōu)先查詢(xún)中最能減少掃描范圍的條件放前
穩(wěn)定性?xún)?yōu)先每次查詢(xún)必帶的條件(如 del_flag)放最后
低區(qū)分度列不單獨(dú)建索引例如 0/1、狀態(tài)、布爾值
用 EXPLAIN 驗(yàn)證執(zhí)行計(jì)劃理論與實(shí)際可能受統(tǒng)計(jì)信息影響

八、推薦實(shí)踐模板

查詢(xún)場(chǎng)景推薦索引
WHERE del_flag=0 AND unit_id=?(unit_id, del_flag)
WHERE del_flag=0 AND user_id=?(user_id, del_flag)
WHERE del_flag=0 AND unit_id=? AND user_id=?(unit_id, user_id, del_flag)

?? 不推薦 (del_flag, unit_id, user_id)
? 推薦 (unit_id, user_id, del_flag)

九、總結(jié)

重點(diǎn)說(shuō)明
? 索引順序決定可用性最左前綴原則
? 區(qū)分度決定效率區(qū)分度高 → 放前面
? WHERE 條件順序無(wú)關(guān)緊要優(yōu)化器會(huì)自動(dòng)重排
? 低區(qū)分度列放前浪費(fèi)索引如 del_flag、status
? 正確索引能提升數(shù)十倍性能用 EXPLAIN 驗(yàn)證

?? 一句話總結(jié):

MySQL 會(huì)自動(dòng)優(yōu)化 WHERE 條件順序,但不會(huì)改變索引定義順序。
因此,請(qǐng)始終把高區(qū)分度字段放在聯(lián)合索引前列,
把低區(qū)分度的 del_flag、status 等放在最后。

到此這篇關(guān)于MySQL聯(lián)合索引設(shè)計(jì)中字段順序、區(qū)分度與優(yōu)化器行為的文章就介紹到這了,更多相關(guān)MySQL聯(lián)合索引字段順序、區(qū)分度與優(yōu)化器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • PostgreSQL與MySQL區(qū)別全面對(duì)比詳析

    PostgreSQL與MySQL區(qū)別全面對(duì)比詳析

    MySQL和PostgreSQL都是強(qiáng)大的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),但它們適用于不同的用例和需求,下面這篇文章主要介紹了PostgreSQL與MySQL區(qū)別全面對(duì)比的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-12-12
  • MySQL的mysqldump工具用法詳解

    MySQL的mysqldump工具用法詳解

    這篇文章主要介紹了MySQL的mysqldump工具用法詳解,同時(shí)附帶了相關(guān)Source命令的用法,詳解需要的朋友可以參考下
    2015-07-07
  • Mysql常見(jiàn)的慢查詢(xún)優(yōu)化方式總結(jié)

    Mysql常見(jiàn)的慢查詢(xún)優(yōu)化方式總結(jié)

    優(yōu)化是一項(xiàng)復(fù)雜的任務(wù),因?yàn)樗罱K需要對(duì)整個(gè)系統(tǒng)的理解,下面這篇文章主要給大家總結(jié)介紹了關(guān)于Mysql常見(jiàn)的慢查詢(xún)優(yōu)化方式,文中介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • MySQL8.0的工具日志配置管理方式

    MySQL8.0的工具日志配置管理方式

    MySQL日志分類(lèi)包括錯(cuò)誤日志(記錄錯(cuò)誤信息)、普通日志(全量操作記錄)、二進(jìn)制日志(用于數(shù)據(jù)恢復(fù)、主從復(fù)制和審計(jì),默認(rèn)8.0開(kāi)啟)、慢日志(記錄性能低的SQL),配置需在my.cnf中設(shè)置,重啟生效,建議分離存儲(chǔ)日錄與數(shù)據(jù)
    2025-07-07
  • 將舊版MySQL替換為8.0及以上版本保姆級(jí)教學(xué)

    將舊版MySQL替換為8.0及以上版本保姆級(jí)教學(xué)

    在部署項(xiàng)目的時(shí)候MySQL就會(huì)報(bào)錯(cuò),這個(gè)時(shí)候就要換MySQL的版本了,這篇文章主要給大家介紹了關(guān)于將舊版MySQL替換為8.0及以上版本的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2024-05-05
  • MySQL報(bào)錯(cuò)Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggre

    MySQL報(bào)錯(cuò)Expression #1 of SELECT list 

    這篇文章主要介紹了MySQL報(bào)錯(cuò)Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggre問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-09-09
  • mysql服務(wù)器無(wú)法啟動(dòng)的解決方法

    mysql服務(wù)器無(wú)法啟動(dòng)的解決方法

    本文主要介紹了mysql服務(wù)器無(wú)法啟動(dòng)的解決方法,mysql服務(wù)器無(wú)法啟動(dòng)時(shí),一般時(shí)配置文件和路徑的問(wèn)題,下面就來(lái)介紹一下解決方法,感興趣的可以了解一下
    2023-09-09
  • MySQL安全設(shè)置圖文教程

    MySQL安全設(shè)置圖文教程

    MySQL安全設(shè)置,跟mssql差不多都是以普通用戶(hù)權(quán)限運(yùn)行mysql。其它的也需要注意下。
    2011-01-01
  • mysql解壓包的安裝基礎(chǔ)教程

    mysql解壓包的安裝基礎(chǔ)教程

    這篇文章主要為大家詳細(xì)介紹了mysql解壓包的安裝基礎(chǔ)教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • 詳解MySQL中DISTINCT去重的核心注意事項(xiàng)

    詳解MySQL中DISTINCT去重的核心注意事項(xiàng)

    為了實(shí)現(xiàn)查詢(xún)不重復(fù)的數(shù)據(jù),MySQL 提供了DISTINCT關(guān)鍵字,它的主要作用就是對(duì)數(shù)據(jù)表中一個(gè)或多個(gè)字段重復(fù)的數(shù)據(jù)進(jìn)行過(guò)濾,只返回其中的一條數(shù)據(jù)給用戶(hù),下面小編就來(lái)和大家簡(jiǎn)單講講DISTINCT去重的核心注意事項(xiàng)吧
    2025-06-06

最新評(píng)論

新巴尔虎左旗| 翼城县| 修武县| 临朐县| 皮山县| 双辽市| 永修县| 抚顺县| 普陀区| 赣榆县| 武陟县| 河间市| 孟连| 巧家县| 博白县| 富宁县| 台安县| 宣汉县| 青州市| 马边| 元江| 射阳县| 博罗县| 通州区| 墨脱县| 太原市| 新津县| 新蔡县| 富平县| 图木舒克市| 卓资县| 辰溪县| 长顺县| 湘潭市| 社会| 满洲里市| 会同县| 黄骅市| 廉江市| 柏乡县| 渭源县|