MySQL帶你秒懂索引下推
索引下推(Index Condition Pushdown
,簡(jiǎn)稱(chēng)ICP
),是MySQL5.6
版本的新特性,它能減少回表查詢(xún)次數(shù),提高查詢(xún)效率。
一、索引下推優(yōu)化的原理
我們先簡(jiǎn)單了解一下MySQL大概的架構(gòu):
MySQL服務(wù)層負(fù)責(zé)SQL語(yǔ)法解析、生成執(zhí)行計(jì)劃等,并調(diào)用存儲(chǔ)引擎層去執(zhí)行數(shù)據(jù)的存儲(chǔ)和檢索。
索引下推
的下推其實(shí)就是指將部分上層(服務(wù)層)負(fù)責(zé)的事情,交給了下層(引擎層)去處理。
我們來(lái)具體看一下,在沒(méi)有使用ICP的情況下,MySQL的查詢(xún):
- 存儲(chǔ)引擎讀取索引記錄;
- 根據(jù)索引中的主鍵值,定位并讀取完整的行記錄;
- 存儲(chǔ)引擎把記錄交給Server層去檢測(cè)該記錄是否滿(mǎn)足WHERE條件。
使用ICP的情況下,查詢(xún)過(guò)程:
- 存儲(chǔ)引擎讀取索引記錄(不是完整的行記錄);
- 判斷WHERE條件部分能否用索引中的列來(lái)做檢查,條件不滿(mǎn)足,則處理下一行索引記錄;
- 條件滿(mǎn)足,使用索引中的主鍵去定位并讀取完整的行記錄(就是所謂的回表);
- 存儲(chǔ)引擎把記錄交給Server層,Server層檢測(cè)該記錄是否滿(mǎn)足WHERE條件的其余部分。
二、索引下推的具體實(shí)踐
理論比較抽象,我們來(lái)上一個(gè)實(shí)踐。
使用一張用戶(hù)表tuser
,表里創(chuàng)建聯(lián)合索引(name, age)。
如果現(xiàn)在有一個(gè)需求:檢索出表中名字第一個(gè)字是張,而且年齡是10歲的所有用戶(hù)。那么,SQL語(yǔ)句是這么寫(xiě)的:
select * from tuser where name like '張%' and age=10;
假如你了解索引最左匹配原則,那么就知道這個(gè)語(yǔ)句在搜索索引樹(shù)的時(shí)候,只能用 張,找到的第一個(gè)滿(mǎn)足條件的記錄id為1。
那接下來(lái)的步驟是什么呢?
1、沒(méi)有使用ICP
在MySQL 5.6
之前,存儲(chǔ)引擎根據(jù)通過(guò)聯(lián)合索引找到name like
'張%' 的主鍵id(1、4),逐一進(jìn)行回表掃描,去聚簇索引找到完整的行記錄,server
層再對(duì)數(shù)據(jù)根據(jù)age=10
進(jìn)行篩選。
我們看一下示意圖:
可以看到需要回表兩次,把我們聯(lián)合索引的另一個(gè)字段age
浪費(fèi)了。
2、使用ICP
而MySQL 5.6
以后, 存儲(chǔ)引擎根據(jù)(name
,age
)聯(lián)合索引,找到name like '張%
',由于聯(lián)合索引中包含age
列,所以存儲(chǔ)引擎直接再聯(lián)合索引里按照age=10
過(guò)濾。按照過(guò)濾后的數(shù)據(jù)再一一進(jìn)行回表掃描。
我們看一下示意圖:
可以看到只回表了一次。
除此之外我們還可以看一下執(zhí)行計(jì)劃,看到Extra
一列里 Using index condition
,這就是用到了索引下推。
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+ | 1 | SIMPLE | tuser | NULL | range | na_index | na_index | 102 | NULL | 2 | 25.00 | Using index condition | +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+
三、索引下推使用條件
- 只能用于
range
、ref
、eq_ref
、ref_or_null
訪問(wèn)方法; - 只能用于
InnoDB
和MyISAM
存儲(chǔ)引擎及其分區(qū)表; - 對(duì)
InnoDB
存儲(chǔ)引擎來(lái)說(shuō),索引下推只適用于二級(jí)索引(也叫輔助索引);
索引下推的目的是為了減少回表次數(shù),也就是要減少I(mǎi)O操作。對(duì)于InnoDB的聚簇索引來(lái)說(shuō),
數(shù)據(jù)和索引
是在一起的,不存在回表這一說(shuō)。
- 引用了子查詢(xún)的條件不能下推;
- 引用了存儲(chǔ)函數(shù)的條件不能下推,因?yàn)榇鎯?chǔ)引擎無(wú)法調(diào)用存儲(chǔ)函數(shù)。
相關(guān)系統(tǒng)參數(shù):
索引條件下推默認(rèn)是開(kāi)啟的,可以使用系統(tǒng)參數(shù)optimizer_switch來(lái)控制器是否開(kāi)啟。
查看默認(rèn)狀態(tài):
mysql> select @@optimizer_switch\G; *************************** 1. row *************************** @@optimizer_switch: index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,duplicateweedout=on,subquery_materialization_cost_based=on,use_index_extensions=on,condition_fanout_filter=on,derived_merge=on 1 row in set (0.00 sec)
切換狀態(tài):
set optimizer_switch="index_condition_pushdown=off"; set optimizer_switch="index_condition_pushdown=on";
到此這篇關(guān)于幾分鐘搞懂MySQL索引下推的文章就介紹到這了,更多相關(guān)MySQL索引下推內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
常見(jiàn)的十種SQL語(yǔ)句性能優(yōu)化策略詳解
這篇文章主要介紹了常見(jiàn)的十種SQL語(yǔ)句性能優(yōu)化策略詳解,SQL語(yǔ)句性能優(yōu)化是提高數(shù)據(jù)庫(kù)查詢(xún)效率的關(guān)鍵步驟,可以減少查詢(xún)時(shí)間,提高系統(tǒng)響應(yīng)速度,本文將介紹一些常見(jiàn)的SQL語(yǔ)句性能優(yōu)化技巧,包括索引的使用、合理的查詢(xún)條件、避免全表掃描等,需要的朋友可以參考下2023-10-10mysql5.7.19 解壓版安裝教程詳解(附送純凈破解中文版SQLYog)
Mysql5.7.19版本是今年新推出的版本,最近幾個(gè)版本的MySQL都不再是安裝版,都是解壓版了,大家在使用過(guò)程中遇到很多問(wèn)題,下面小編給大家?guī)?lái)了MySQL5.7.19 解壓版安裝教程詳解,感興趣的朋友一起看看吧2017-10-10MySQL數(shù)據(jù)庫(kù)查詢(xún)性能優(yōu)化的4個(gè)技巧干貨
這篇文章主要為大家介紹了MySQL數(shù)據(jù)庫(kù)查詢(xún)性能優(yōu)化的4個(gè)技巧干貨詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08Mysql查詢(xún)時(shí)間區(qū)間日期列表實(shí)例代碼
最近常用到mysql的日期范圍搜索,下面這篇文章主要給大家介紹了關(guān)于Mysql查詢(xún)時(shí)間區(qū)間日期列表的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04關(guān)于MySql 10038錯(cuò)誤的完美解決方法(三種)
本文給大家?guī)?lái)三種有關(guān)mysql報(bào)10038錯(cuò)誤的解決方法,每種方法都非常不錯(cuò),需要的朋友參考下2016-09-09SQL中寫(xiě)入包含有英文單引號(hào)“ '''' ”失敗問(wèn)題深入詳解
這篇文章主要介紹了SQL中寫(xiě)入包含有英文單引號(hào)“ ' ”失敗問(wèn)題深入詳解,列舉了具體實(shí)例講解,有感興趣的同學(xué)可以研究下2021-03-03mysql 5.7更改數(shù)據(jù)庫(kù)的數(shù)據(jù)存儲(chǔ)位置的解決方法
隨著MySQL數(shù)據(jù)庫(kù)存儲(chǔ)的數(shù)據(jù)逐漸變大,已經(jīng)將原來(lái)的存儲(chǔ)數(shù)據(jù)的空間占滿(mǎn)了,導(dǎo)致mysql已經(jīng)鏈接不上了。所以要給存放的數(shù)據(jù)換個(gè)地方,下面小編給大家分享mysql 5.7更改數(shù)據(jù)庫(kù)的數(shù)據(jù)存儲(chǔ)位置的解決方法,一起看看吧2017-04-04