0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

MySQL索引下推知識(shí)分享

OSC開(kāi)源社區(qū) ? 來(lái)源:OSCHINA 社區(qū) ? 2022-12-27 09:49 ? 次閱讀

作者 | 京東云開(kāi)發(fā)者-劉鄧忠

Mysql 是大家最常用的數(shù)據(jù)庫(kù),下面為大家?guī)?lái) mysql 索引下推知識(shí)點(diǎn)的分享,以便鞏固 mysql 基礎(chǔ)知識(shí),如有錯(cuò)誤,還請(qǐng)各位大佬們指正。

1 什么是索引下推

索引下推 (Index Condition Pushdown,索引條件下推,簡(jiǎn)稱 ICP),是 MySQL5.6 版本的新特性,它可以在對(duì)聯(lián)合索引遍歷過(guò)程中,對(duì)索引中包含的所有字段先做判斷,過(guò)濾掉不符合條件的記錄之后再回表,能有效的減少回表次數(shù)(目前我們使用的 mysql 版本較高,一般大家可能感覺(jué)這是正常的,但是 mysql5.6 之前都不是這樣實(shí)現(xiàn)的,下面會(huì)細(xì)細(xì)道來(lái))。

1.1 適用條件

我們先來(lái)了解一下索引下推的使用條件及限制:

只支持 select。

當(dāng)需要訪問(wèn)全表時(shí),ICP 用于 range,ref,eq_ref 和 ref_or_null 訪問(wèn)類型。

ICP 可用于 InnoDB 和 MyISAM 表,包括分區(qū)的 InnoDB 和 MyISAM 表。(5.6 版本不適用分區(qū)表查詢,5.7 版本后可以用于分區(qū)表查詢)。

對(duì)于 InnDB 引擎只適用于二級(jí)索引(也叫輔助索引),因?yàn)?InnDB 的聚簇索引會(huì)將整行數(shù)據(jù)讀到 InnDB 的緩沖區(qū),這樣一來(lái)索引條件下推的主要目的減少 IO 次數(shù)就失去了意義。因?yàn)閿?shù)據(jù)已經(jīng)在內(nèi)存中了,不再需要去讀取了。

在虛擬生成列上創(chuàng)建的輔助索引不支持 ICP(注:InnoDB 支持虛擬生成列的輔助索引)。

使用了子查詢的條件無(wú)法下推。

使用存儲(chǔ)過(guò)程或函數(shù)的條件無(wú)法下推(因?yàn)橐驗(yàn)榇鎯?chǔ)引擎沒(méi)有調(diào)用存儲(chǔ)過(guò)程或函數(shù)的能力)。

觸發(fā)條件無(wú)法下推。(有關(guān)觸發(fā)條件的信息,請(qǐng)參閱官方資料:Section 8.2.2.3, “Optimizing Subqueries with the EXISTS Strategy”.。)

1.2 原理介紹

首先,我們大致回顧下 mysql 的基本架構(gòu):

374cf660-852e-11ed-bfe3-dac502259ad0.png

MySQL 基本的架構(gòu)示例圖 MySQL 服務(wù)層主要負(fù)責(zé) SQL 語(yǔ)法解析、生成執(zhí)行計(jì)劃等,并調(diào)用存儲(chǔ)引擎層去執(zhí)行數(shù)據(jù)的存儲(chǔ)和查詢。

索引下推的下推其含義就是指將部分上層(服務(wù)層)負(fù)責(zé)的事情,交給了下層(引擎層)去處理。

在 MySql 5.6 版本之前沒(méi)有索引下推這個(gè)功能,從 5.6 版本后才加上了這個(gè)優(yōu)化項(xiàng)。我們先簡(jiǎn)單對(duì)比一下使用和未使用 ICP 兩種情況下,MySql 的查詢過(guò)程吧。

1) 未使用 ICP 的情況下:

- 存儲(chǔ)引擎讀取索引記錄;

- 根據(jù)索引中的主鍵值,定位并讀取完整的行記錄;

- 存儲(chǔ)引擎把記錄交給 Server 層去檢測(cè)該記錄是否滿足 WHERE 條件。

2) 使用 ICP 的情況下:

- 存儲(chǔ)引擎讀取索引記錄(不是完整的行記錄);

- 判斷 WHERE 條件部分能否用索引中的列來(lái)做檢查,條件不滿足,則處理下一行索引記錄;

- 條件滿足,使用索引中的主鍵去定位并讀取完整的行記錄(就是所謂的回表);

- 存儲(chǔ)引擎把記錄交給 Server 層,Server 層檢測(cè)該記錄是否滿足 WHERE 條件的其余部分。

2 具體示例

上面介紹了基本原理,下面使用示例,帶大家更直觀的進(jìn)行理解(注:以下示例基于 InnoDB 存儲(chǔ)引擎。)

首先,我們新建一張用戶表(jxc_user),設(shè)置 id 為主鍵索引,并創(chuàng)建聯(lián)合索引(name, age)。

376f2da2-852e-11ed-bfe3-dac502259ad0.png

我們先看一下該表主鍵索引的大致結(jié)構(gòu)示例:

37897810-852e-11ed-bfe3-dac502259ad0.png

主鍵索引結(jié)構(gòu)示例圖 然后我們?cè)倏匆幌略摫砺?lián)合索引的大致結(jié)構(gòu)示例:

37a9d7d6-852e-11ed-bfe3-dac502259ad0.png

聯(lián)合索引結(jié)構(gòu)示例圖 如果現(xiàn)在有一個(gè)需求,要求檢索出表中名字第一個(gè)字是張,而且年齡等于 10 歲的所有用戶。示例 SQL 語(yǔ)句如下:

select id,name,age,tel,addr from jxc_user where name like '張%' and age=10;

根據(jù)索引最左匹配原則,上面這個(gè) sql 語(yǔ)句在查索引樹(shù)的時(shí)候,只能用 “張”,查到第一個(gè)滿足條件的記錄:id 為 1。

那接下來(lái)我們具體看一下 使用與未使用 ICP 的情況。

2.1 未使用 ICP 的情況

在 MySQL 5.6 之前,存儲(chǔ)引擎根據(jù)聯(lián)合索引先找到 name like ‘張 %’ 的主鍵 id(1、4),再逐一進(jìn)行回表掃描,去聚簇索引找到完整的行記錄,返回 server 層,server 層拿到數(shù)據(jù)后,再根據(jù)條件 age=10 對(duì)拿到的數(shù)據(jù)進(jìn)行篩選。大致的示意圖如下:

37decd1a-852e-11ed-bfe3-dac502259ad0.png

從上圖,可以看到需要回表兩次,存儲(chǔ)引擎并不會(huì)去按照 age=10 進(jìn)行過(guò)濾,相當(dāng)于聯(lián)合索引的另一個(gè)字段 age 在存儲(chǔ)引擎層沒(méi)有發(fā)揮作用,比較浪費(fèi)。

2.2 使用 ICP 的情況

而 MySQL 5.6 以后, 存儲(chǔ)引擎會(huì)根據(jù)(name,age)聯(lián)合索引,找到 name like ‘張 %’,由于聯(lián)合索引中包含 age 列,所以存儲(chǔ)引擎直接再聯(lián)合索引里按照條件 age=10 進(jìn)行過(guò)濾,然后根據(jù)過(guò)濾后的數(shù)據(jù)再依次進(jìn)行回表掃描。大致的示意圖如下:

3817a1b2-852e-11ed-bfe3-dac502259ad0.png

從上圖,可以看到只是 id=1 的數(shù)據(jù),回表了一次。 除此之外我們還可以看一下執(zhí)行計(jì)劃,看到 Extra 一列里 Using index condition,就是用到了索引下推。

3841dafe-852e-11ed-bfe3-dac502259ad0.png

3 控制參數(shù)

Mysql 索引下推功能默認(rèn)是開(kāi)啟的,可以用系統(tǒng)參數(shù) optimizer_switch 來(lái)控制是否開(kāi)啟。

查看狀態(tài)命令:

select @@optimizer_switch;

386779e4-852e-11ed-bfe3-dac502259ad0.png

關(guān)閉命令:set optimizer_switch=”index_condition_pushdown=off”;

開(kāi)啟命令:set optimizer_switch=”index_condition_pushdown=on”;

4 總結(jié)

回表操作:當(dāng)所要查找的字段不在非主鍵索引樹(shù)上時(shí),需要通過(guò)葉子節(jié)點(diǎn)的主鍵值去主鍵索引上獲取對(duì)應(yīng)的行數(shù)據(jù),這個(gè)過(guò)程稱為回表操作。

索引下推:索引下推主要是減少了不必要的回表操作。對(duì)于查找出來(lái)的數(shù)據(jù),先過(guò)濾掉不符合條件的,其余的再去主鍵索引樹(shù)上查找。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)庫(kù)
    +關(guān)注

    關(guān)注

    7

    文章

    3799

    瀏覽量

    64395
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    809

    瀏覽量

    26574
  • ICP
    ICP
    +關(guān)注

    關(guān)注

    0

    文章

    70

    瀏覽量

    12788

原文標(biāo)題:MySQL索引下推知識(shí)分享

文章出處:【微信號(hào):OSC開(kāi)源社區(qū),微信公眾號(hào):OSC開(kāi)源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    #硬聲創(chuàng)作季 【MySQL調(diào)優(yōu)】聚集索引與覆蓋索引索引下推到底是什么

    數(shù)據(jù)庫(kù)MySQL
    Mr_haohao
    發(fā)布于 :2022年09月14日 07:35:53

    MySQL索引的創(chuàng)建與刪除

    MySQL——索引技巧以及注意事項(xiàng)
    發(fā)表于 10-31 09:27

    詳解mysql索引

    mysql索引簡(jiǎn)介
    發(fā)表于 04-13 06:50

    mysql索引使用技巧有哪些?

    mysql索引使用技巧
    發(fā)表于 05-20 06:09

    基于MySQL索引的壓力測(cè)試

    MySQL - 基于索引的壓力測(cè)試
    發(fā)表于 06-13 07:57

    MySQL索引使用優(yōu)化和規(guī)范

    MySQL - 索引使用優(yōu)化和規(guī)范
    發(fā)表于 06-15 16:01

    MySQL索引、事務(wù)、視圖介紹

    MySQL--索引、事務(wù)、視圖
    發(fā)表于 06-15 07:05

    MySQL索引使用原則

    一般來(lái)說(shuō), MySQL 中的 B-Tree 索引的物理文件大多都是以 Balance Tree 的結(jié)構(gòu)來(lái)存儲(chǔ)的,也就是所有實(shí)際需要的數(shù)據(jù)都存放于 Tree 的 Leaf Node(葉子節(jié)點(diǎn)) ,而且
    的頭像 發(fā)表于 02-11 15:17 ?2722次閱讀
    <b class='flag-5'>MySQL</b><b class='flag-5'>索引</b>使用原則

    MySQL索引的使用問(wèn)題

    、MySQL 在LIKE進(jìn)行模糊匹配的時(shí)候又是如何利用索引的呢?3、MySQL 到底在怎么樣的情況下能夠利用索引進(jìn)行排序?今天,我將會(huì)用一個(gè)模型,把這些問(wèn)題都一一解答,讓你對(duì)
    的頭像 發(fā)表于 01-06 16:13 ?1613次閱讀

    關(guān)于MySQL索引的分類與原理及本質(zhì)解析

    索引,可能讓好很多人望而生畏,畢竟每次面試時(shí)候 MySQL索引一定是必問(wèn)內(nèi)容,哪怕先撇開(kāi)面試,就在平常的開(kāi)發(fā)中,對(duì)于 SQL 的優(yōu)化也而是重中之重。
    的頭像 發(fā)表于 04-03 11:56 ?1621次閱讀
    關(guān)于<b class='flag-5'>MySQL</b>中<b class='flag-5'>索引</b>的分類與原理及本質(zhì)解析

    一百道關(guān)于MySQL索引解答

    數(shù)據(jù)庫(kù) 1. MySQL索引使用有哪些注意事項(xiàng)呢? 可以從三個(gè)維度回答這個(gè)問(wèn)題:索引哪些情況會(huì)失效,索引不適合哪些場(chǎng)景,索引規(guī)則
    的頭像 發(fā)表于 06-13 15:51 ?2102次閱讀

    MySQL高級(jí)進(jìn)階:索引優(yōu)化

    MySQL官方對(duì)于索引的定義:索引是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。
    的頭像 發(fā)表于 06-11 11:13 ?578次閱讀
    <b class='flag-5'>MySQL</b>高級(jí)進(jìn)階:<b class='flag-5'>索引</b>優(yōu)化

    MySQL索引的常用知識(shí)點(diǎn)

    索引結(jié)構(gòu):B+樹(shù) 索引其實(shí)是一種數(shù)據(jù)結(jié)構(gòu) 注意B+樹(shù)是MySQL,索引默認(rèn)的結(jié)構(gòu);一張表至少有一個(gè)索引(主鍵
    的頭像 發(fā)表于 09-30 16:43 ?464次閱讀

    導(dǎo)致MySQL索引失效的情況以及相應(yīng)的解決方法

    導(dǎo)致MySQL索引失效的情況以及相應(yīng)的解決方法? MySQL索引的目的是提高查詢效率,但有些情況下索引可能會(huì)失效,導(dǎo)致查詢變慢或效果不如預(yù)期
    的頭像 發(fā)表于 12-28 10:01 ?761次閱讀

    一文了解MySQL索引機(jī)制

    接觸MySQL數(shù)據(jù)庫(kù)的小伙伴一定避不開(kāi)索引,索引的出現(xiàn)是為了提高數(shù)據(jù)查詢的效率,就像書的目錄一樣。 某一個(gè)SQL查詢比較慢,你第一時(shí)間想到的就是“給某個(gè)字段加個(gè)索引吧”,那么
    的頭像 發(fā)表于 07-25 14:05 ?295次閱讀
    一文了解<b class='flag-5'>MySQL</b><b class='flag-5'>索引</b>機(jī)制