MySQL索引下推詳細(xì)
前言:
索引下推(ICP)是針對(duì)MySQL使用索引從表中檢索數(shù)據(jù)行的情況的優(yōu)
- 在沒有索引下推的情況下,MySQL通過存儲(chǔ)引擎遍歷索引來定位表中的數(shù)據(jù)行并將它們返回給MySQl服務(wù)器,服務(wù)器再進(jìn)行WHERE條件的判斷,確認(rèn)是否將數(shù)據(jù)行加入結(jié)果集。
- 開啟索引下推,且WHERE條件部分可以僅使用索引中的列來評(píng)估,這時(shí)MySQL服務(wù)器會(huì)將這部分WHERE條件下推到存儲(chǔ)引擎,接著存儲(chǔ)引擎使用索引條目評(píng)估推送的索引條件,僅當(dāng)滿足該條件時(shí)才從表中進(jìn)行讀取
索引下推可以減少存儲(chǔ)引擎訪問數(shù)據(jù)表的次數(shù)以及MySQL服務(wù)器訪問存儲(chǔ)引擎的次數(shù)。
是不是還有點(diǎn)懵呢,那就對(duì)了,毫無疑問上面這段話理解起來相當(dāng)費(fèi)勁,但請不要灰心,我將用最通俗易懂的語言來帶你了解索引下推。
總結(jié)一下:
- 最左前綴原則
- 回表
1、最左前綴原則
MySQL
在建立聯(lián)合索引時(shí)會(huì)遵循最左前綴原則,比如現(xiàn)在User表建立了聯(lián)合索引(id,name,age)根據(jù)最左前綴原則只有在SQL的條件部分命中(id)、(id,name)或者(id
, name
, age
)時(shí)才能使用到這個(gè)聯(lián)合索引。
能使用該索引的情況如下:
SELECT * FROM USER WHERE id = 1 SELECT * FROM USER WHERE id = 1 and name = 'zhangsan' SELECT * FROM USER WHERE id = 1 and name = 'zhangsan' and age = 18
不能使用該索引的情況如下:
SELECT * FROM USER WHERE name = 'zhangsan' SELECT * FROM USER WHERE age = 18 SELECT * FROM USER WHERE name = 'zhangsan' and age = 18
對(duì)于聯(lián)合索引mysql
會(huì)一直向右匹配直到遇到范圍查詢(>、<、between
、like
)就停止匹配。
2、回表
MySQL
在InnoDB
引擎下支持兩種索引
- 聚集索引 :索引里(B+樹的葉子結(jié)點(diǎn)上)存儲(chǔ)的是數(shù)據(jù)行(真實(shí)的數(shù)據(jù))
- 普通索引 :索引里(B+樹的葉子結(jié)點(diǎn)上)存儲(chǔ)的是主鍵
這里著重說一下聚集索引,官方文檔有以下描述
- 在有主鍵的表,
InnoDB
將主鍵作為聚集索引 - 沒有主鍵的表,
InnoDB
使用第一個(gè)唯一索引作為聚集索引 - 即沒有主鍵也沒有唯一索引時(shí),MySQL將生成一個(gè)隱藏的6字節(jié)大小的
row ID
字段作為聚集索引
MySQL
通過普通索引沒法一次性將數(shù)據(jù)拿全的情況下,通過普通索引獲取主鍵值,再通過主鍵值到聚集索引中定位到記錄,這個(gè)過程就叫回表??梢酝ㄟ^建立覆蓋索引來減少回表,比如現(xiàn)在要通過身份證號(hào)查姓名,那就建立身份證號(hào)和姓名的聯(lián)合索引(id
,name
),當(dāng)查詢時(shí)可以通過這個(gè)索引直接拿到姓名name
得值,不再需要去聚集索引里查找了,這就是覆蓋索引。
3、索引下推
首先創(chuàng)建一個(gè)用戶表
CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `age` int DEFAULT 0, `class` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), KEY `index_two` (`name`,`age`) ) ENGINE=InnoDB; //這張表增加一個(gè)復(fù)合索引 (`name`,`age`)
給表插入數(shù)據(jù)
INSERT INTO `student` (`name`, `age`, `class`) VALUES ('pengpeng', 21, '1'); INSERT INTO `student` (`name`, `age`, `class`) VALUES ('pengpeng', 22, '2'); INSERT INTO `student` (`name`, `age`, `class`) VALUES ('pengpeng', 23, '3'); INSERT INTO `student` (`name`, `age`, `class`) VALUES ('pengpeng', 24, '4'); INSERT INTO `student` (`name`, `age`, `class`) VALUES ('pengpeng', 25, '5');
查詢插入的數(shù)據(jù)如下
接下來explain下面這個(gè)SQL
explain select * from student where name like 'peng%' and age = 23;
可以看到Extra字段顯示為USING INDEX CONDITION,這就表明這個(gè)SQL使用了索引下推,我們分析下上面這個(gè)SQL語句:
在MySQL5.6之前,只能從name字段中找出符合條件的行然后開始回表,到聚集索引上找出數(shù)據(jù)行,再對(duì)age字段進(jìn)行對(duì)比,把符合條件的數(shù)據(jù)加入到結(jié)果集中。
在MySQL5.6引入了索引下推優(yōu)化,在索引的遍歷過程中,對(duì)索引中包含字段先做判斷,這里對(duì)age字段進(jìn)行判斷。直接將age字段不滿足的數(shù)據(jù)行排除,從而減少回表的次數(shù)。
問答區(qū)
問題1 當(dāng)復(fù)合索引列為(name,age,address)時(shí) 以下SQL能使用索引嗎?
select * from student where name like 'peng%' and age = 23;
可以,遇到like會(huì)中斷后續(xù)元素的匹配,但只能使用name這個(gè)字段,mysql會(huì)一直向右匹配直到遇到范圍查詢(>、<、between、like)就停止匹配。范圍列可以用到索引,但是范圍列后面的列無法用到索引。即索引最多用于一個(gè)范圍列,因此如果查詢條件中有兩個(gè)范圍列則無法全用到索引。
問題2 索引下推只能存在聯(lián)合索引里嗎?
是的,非聯(lián)合索引無法使用索引下推。
問題3 索引下推在哪些情況下無法使用?
下推條件遇到子查詢
下推條件遇到函數(shù)
非InnoDB表和MyISAM表
問題4 索引下推如何開啟和關(guān)閉?
// 索引下推默認(rèn)是開啟的 set optimizer_switch='index_condition_pushdown=off'; // 關(guān)閉 set optimizer_switch='index_condition_pushdown=on'; // 開啟
總結(jié)
索引下推在非主鍵索引上的優(yōu)化,可以有效減少回表的次數(shù),大大提升了查詢的效率,在平時(shí)工作中可以根據(jù)業(yè)務(wù)情況通過優(yōu)化索引來達(dá)到使用索引下推,提高業(yè)務(wù)吞吐量。
到此這篇關(guān)于MySQL索引下推詳細(xì)的文章就介紹到這了,更多相關(guān)MySQL索引下推內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL curdate()函數(shù)的實(shí)例詳解
這篇文章主要介紹了MySQL curdate()函數(shù)的實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家理解應(yīng)用MysqL curdate()的使用方法,需要的朋友可以參考下2017-09-09mysql5.5 master-slave(Replication)配置方法
mysql5.5 master-slave(Replication)配置方法,需要的朋友可以參考下。2011-08-08ubuntu mysql 5.6版本的刪除/安裝/編碼配置文件配置
這篇文章主要介紹了ubuntu mysql 5.6版本的刪除,安裝,編碼配置文件配置,需要的朋友可以參考下2017-06-06Mysql如何對(duì)json數(shù)據(jù)進(jìn)行查詢及修改
這篇文章主要介紹了Mysql如何對(duì)json數(shù)據(jù)進(jìn)行查詢及修改,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07MYSQL row_number()與over()函數(shù)用法詳解
這篇文章主要介紹了MYSQL row_number()與over()函數(shù)用法詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08SQL的substring_index()用法實(shí)例(MySQL字符串截取)
substring_index?(字符串,分隔符,序號(hào)),主要作用是用于截取目標(biāo)字符串,下面這篇文章主要給大家介紹了關(guān)于SQL中substring_index()用法(MySQL字符串截取)的相關(guān)資料,需要的朋友可以參考下2023-01-01