MySQL索引下推(ICP)的簡(jiǎn)單理解與示例
前言
索引下推(Index Condition Pushdown, 簡(jiǎn)稱(chēng)ICP)是MySQL 5.6 版本的新特性,它能減少回表查詢(xún)次數(shù),提升檢索效率。
MySQL體系結(jié)構(gòu)
要明白索引下推,首先要了解MySQL的體系結(jié)構(gòu):

上圖來(lái)自MySQL官方文檔。
通常把MySQL從上至下分為以下幾層:
- MySQL服務(wù)層:包括NoSQL和SQL接口、查詢(xún)解析器、優(yōu)化器、緩存和Buffer等組件。
- 存儲(chǔ)引擎層:各種插件式的表格存儲(chǔ)引擎,實(shí)現(xiàn)事務(wù)、索引等各種存儲(chǔ)引擎相關(guān)的特性。
- 文件系統(tǒng)層: 讀寫(xiě)物理文件。
MySQL服務(wù)層負(fù)責(zé)SQL語(yǔ)法解析、觸發(fā)器、視圖、內(nèi)置函數(shù)、binlog、生成執(zhí)行計(jì)劃等,并調(diào)用存儲(chǔ)引擎層去執(zhí)行數(shù)據(jù)的存儲(chǔ)和檢索?!八饕峦啤钡摹跋隆逼鋵?shí)就是指將部分上層(服務(wù)層)負(fù)責(zé)的事情,交給了下層(存儲(chǔ)引擎)去處理。
索引下推案例
假設(shè)用戶(hù)表數(shù)據(jù)和結(jié)構(gòu)如下:
| id | age | birthday | name |
|---|---|---|---|
| 1 | 18 | 01-01 | User1 |
| 2 | 19 | 03-01 | User2 |
| 3 | 20 | 03-01 | User3 |
| 4 | 21 | 03-01 | User4 |
| 5 | 22 | 05-01 | User5 |
| 6 | 18 | 06-01 | User6 |
| 7 | 24 | 01-01 | User7 |
創(chuàng)建一個(gè)聯(lián)合索引(age, birthday),并查詢(xún)出年齡>20,且生日為03-01的用戶(hù):
select * from user where age>20 and birthday="03-01"
由于age字段使用了范圍查詢(xún),根據(jù)最左前綴原則,這種情況只能使用age字段進(jìn)行范圍查詢(xún),索引中的birthday字段無(wú)法使用。使用explain查看執(zhí)行計(jì)劃:
+------+-------------+-------+-------+---------------+--------------+---------+------+------+-----------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+-------------+-------+-------+---------------+--------------+---------+------+------+-----------------------+ | 1 | SIMPLE | user | range | age_birthday | age_birthday | 4 | NULL | 3 | Using index condition | +------+-------------+-------+-------+---------------+--------------+---------+------+------+-----------------------+
可以看到雖然使用了age_birthday索引,但是索引長(zhǎng)度key_len只有4,說(shuō)明只有聯(lián)合索引只有age字段生效了(因?yàn)閍ge字段是int類(lèi)型,占用4個(gè)字節(jié))。最后Extra列的Using index condition表示這個(gè)查詢(xún)使用了索引下推優(yōu)化。
為在沒(méi)有索引下推的情況下,執(zhí)行步驟如下:
- 存儲(chǔ)引擎根據(jù)索引查找出age>20的用戶(hù)id,分別是:4,5,7
- 存儲(chǔ)引擎到表格中取出id in (4,5,7)的3條記錄,返回給服務(wù)層
- 服務(wù)層過(guò)濾掉不符合birthday="03-01"條件的記錄,最后返回查詢(xún)結(jié)果為id=4的1行記錄。
如果開(kāi)啟了索引下推優(yōu)化,執(zhí)行步驟如下:
- 存儲(chǔ)引擎根據(jù)索引查找出age>20的用戶(hù)id,并使用索引中的birthday字段過(guò)濾掉不符合birthday="03-01"條件的記錄,最后得到id=4;
- 存儲(chǔ)引擎到表格中取出id=4的1條記錄,返回給服務(wù)層;
- 服務(wù)層過(guò)濾掉不符合birthday="03-01"條件的記錄,最后返回查詢(xún)結(jié)果為id=4的1行記錄。
啟用索引下推后,把where條件由MySQL服務(wù)層放到了存儲(chǔ)引擎層去執(zhí)行,帶來(lái)的好處就是存儲(chǔ)引擎根據(jù)id到表格中讀取數(shù)據(jù)的次數(shù)變少了。在上面這個(gè)例子中,沒(méi)有索引下推時(shí)需要多回表查詢(xún)2次。并且回表查詢(xún)很可能是離散IO,在某些情況下,對(duì)數(shù)據(jù)庫(kù)性能會(huì)有較大提升。
總結(jié)
到此這篇關(guān)于MySQL索引下推(ICP)的簡(jiǎn)單理解與示例的文章就介紹到這了,更多相關(guān)MySQL索引下推(ICP)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
自學(xué)MySql內(nèi)置函數(shù)知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家整理的是關(guān)于MySql內(nèi)置函數(shù)的知識(shí)點(diǎn)總結(jié)內(nèi)容,需要的朋友們可以學(xué)習(xí)參考下。2020-01-01
mysql group by having 實(shí)例代碼
mysql中g(shù)roup by語(yǔ)句用于分組查詢(xún),可以根據(jù)給定數(shù)據(jù)列的每個(gè)成員對(duì)查詢(xún)結(jié)果進(jìn)行分組統(tǒng)計(jì),最終得到一個(gè)分組匯總表, 經(jīng)常和having一起使用,需要的朋友可以參考下2016-11-11
CentOS7安裝MySQL8的超級(jí)詳細(xì)教程(無(wú)坑!)
我們?cè)贚inux系統(tǒng)中,如果要使用關(guān)系型數(shù)據(jù)庫(kù)的話(huà),基本都是用的mysql,這篇文章主要給大家介紹了關(guān)于CentOS7安裝MySQL8的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06
MySQL數(shù)據(jù)庫(kù)Event定時(shí)執(zhí)行任務(wù)詳解
這篇文章主要介紹了MySQL數(shù)據(jù)庫(kù)Event定時(shí)執(zhí)行任務(wù)2017-12-12
SQL字符型字段按數(shù)字型字段排序?qū)崿F(xiàn)方法

