溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

一文讀懂“建立正確的索引,對(duì)數(shù)據(jù)庫(kù)性能提升的重要性”

發(fā)布時(shí)間:2020-08-09 16:18:14 來(lái)源:ITPUB博客 閱讀:136 作者:云和恩墨 欄目:數(shù)據(jù)庫(kù)



原文: https://www.enmotech.com/web/detail/1/767/1.html 


文章轉(zhuǎn)載自公眾號(hào)  架構(gòu)師之路 架構(gòu)師之路 , 作者 58沈劍


導(dǎo)讀:本文和大家說(shuō)明常見(jiàn)的type結(jié)果及代表的含義,并且通過(guò)同一個(gè)SQL語(yǔ)句的性能差異,說(shuō)明建對(duì)索引多么重要。

 
explain結(jié)果中的type字段代表什么意思?


一文讀懂“建立正確的索引,對(duì)數(shù)據(jù)庫(kù)性能提升的重要性”


MySQL的官網(wǎng)解釋非常簡(jiǎn)潔,只用了3個(gè)單詞:連接類型(the join type)。它描述了找到所需數(shù)據(jù)使用的掃描方式。


最為常見(jiàn)的掃描方式有:

  • system:系統(tǒng)表,少量數(shù)據(jù),往往不需要進(jìn)行磁盤IO;
  • const:常量連接;
  • eq_ref:主鍵索引(primary key)或者非空唯一索引(unique not null)等值掃描;
  • ref:非主鍵非唯一索引等值掃描;
  • range:范圍掃描;
  • index:索引樹(shù)掃描;
  • ALL:全表掃描(full table scan);


畫外音: 這些是最常見(jiàn)的,大家去explain自己工作中的SQL語(yǔ)句,95%都是上面這些類型。
 
上面各類掃描方式由快到慢:
system > const > eq_ref > ref > range > index > ALL


下面一一舉例說(shuō)明。

一、system



一文讀懂“建立正確的索引,對(duì)數(shù)據(jù)庫(kù)性能提升的重要性”


explai select * from mysql.time_zone;

上例中,從系統(tǒng)庫(kù)mysql的系統(tǒng)表time_zone里查詢數(shù)據(jù),掃碼類型為system,這些數(shù)據(jù)已經(jīng)加載到內(nèi)存里,不需要進(jìn)行磁盤IO。


這類掃描是速度最快的。


一文讀懂“建立正確的索引,對(duì)數(shù)據(jù)庫(kù)性能提升的重要性”


explain select * from (select * from user where id=1) tmp;

再舉一個(gè)例子,內(nèi)層嵌套(const)返回了一個(gè)臨時(shí)表,外層嵌套從臨時(shí)表查詢,其掃描類型也是system,也不需要走磁盤IO,速度超快。


二、const



數(shù)據(jù)準(zhǔn)備:

create table user (
id int primary key,
name varchar(20)
)engine=innodb;
 
insert into user values(1,'shenjian');
insert into user values(2,'zhangsan');
insert into user values(3,'lisi');


一文讀懂“建立正確的索引,對(duì)數(shù)據(jù)庫(kù)性能提升的重要性”


const掃描的條件為:
(1)命中主鍵(primary key)或者唯一(unique)索引;
(2)被連接的部分是一個(gè)常量(const)值;
 
explain select * from user where id=1;
如上例,id是PK,連接部分是常量1。
畫外音:別搞什么類型轉(zhuǎn)換的幺蛾子。
 
這類掃描效率極高,返回?cái)?shù)據(jù)量少,速度非???。


三、eq_ref



數(shù)據(jù)準(zhǔn)備:

create table user (
id int primary key,
name varchar(20)
)engine=innodb;
 
insert into user values(1,'shenjian');
insert into user values(2,'zhangsan');
insert into user values(3,'lisi');
 
create table user_ex (
id int primary key,
age int
)engine=innodb;
 
insert into user_ex values(1,18);
insert into user_ex values(2,20);
insert into user_ex values(3,30);
insert into user_ex values(4,40);
insert into user_ex values(5,50);


一文讀懂“建立正確的索引,對(duì)數(shù)據(jù)庫(kù)性能提升的重要性”


eq_ref掃描的條件為,對(duì)于前表的每一行(row),后表只有一行被掃描。
 
再細(xì)化一點(diǎn):
(1)join查詢;
(2)命中主鍵(primary key)或者非空唯一(unique not null)索引;
(3)等值連接;


explain select * from user,user_ex where user.id=user_ex.id;


如上例,id是主鍵,該join查詢?yōu)閑q_ref掃描。



這類掃描的速度也異常之快。


四、ref



數(shù)據(jù)準(zhǔn)備:

create table user (
id int,
name varchar(20) ,
index(id)
)engine=innodb;
 
insert into user values(1,'shenjian');
insert into user values(2,'zhangsan');
insert into user values(3,'lisi');
 
create table user_ex (
id int,
age int,
index(id)
)engine=innodb;
 
insert into user_ex values(1,18);
insert into user_ex values(2,20);
insert into user_ex values(3,30);
insert into user_ex values(4,40);
insert into user_ex values(5,50);


一文讀懂“建立正確的索引,對(duì)數(shù)據(jù)庫(kù)性能提升的重要性”


如果把上例eq_ref案例中的主鍵索引,改為普通非唯一(non unique)索引。

explain select * from user,user_ex where user.id=user_ex.id;

就由eq_ref降級(jí)為了ref,此時(shí)對(duì)于前表的每一行(row),后表可能有多于一行的數(shù)據(jù)被掃描。

一文讀懂“建立正確的索引,對(duì)數(shù)據(jù)庫(kù)性能提升的重要性”


explain select * from user where id=1;

當(dāng)id改為普通非唯一索引后,常量的連接查詢,也由const降級(jí)為了ref,因?yàn)橐部赡苡卸嘤谝恍械臄?shù)據(jù)被掃描。
 
ref掃描,可能出現(xiàn)在join里,也可能出現(xiàn)在單表普通索引里,每一次匹配可能有多行數(shù)據(jù)返回,雖然它比eq_ref要慢,但它仍然是一個(gè)很快的join類型。


五、range



數(shù)據(jù)準(zhǔn)備:

create table user (
id int primary key,
name varchar(20)
)engine=innodb;
 
insert into user values(1,'shenjian');
insert into user values(2,'zhangsan');
insert into user values(3,'lisi');
insert into user values(4,'wangwu');
insert into user values(5,'zhaoliu');


一文讀懂“建立正確的索引,對(duì)數(shù)據(jù)庫(kù)性能提升的重要性”


range掃描就比較好理解了,它是索引上的范圍查詢,它會(huì)在索引上掃碼特定范圍內(nèi)的值。

explain select * from user where id between 1 and 4;
explain select * from user where idin(1,2,3);
explain select * from user where id>3;

像上例中的between,in,>都是典型的范圍(range)查詢。
畫外音:必須是索引,否則不能批量"跳過(guò)"。


六、index



一文讀懂“建立正確的索引,對(duì)數(shù)據(jù)庫(kù)性能提升的重要性”


index類型,需要掃描索引上的全部數(shù)據(jù)。

explain count (*) from user;

如上例,id是主鍵,該count查詢需要通過(guò)掃描索引上的全部數(shù)據(jù)來(lái)計(jì)數(shù)。
畫外音:此表為InnoDB引擎。
 
它僅比全表掃描快一點(diǎn)。


七、ALL



數(shù)據(jù)準(zhǔn)備:

create table user (
id int,
name varchar(20)
)engine=innodb;
 
insert into user values(1,'shenjian');
insert into user values(2,'zhangsan');
insert into user values(3,'lisi');
 
create table user_ex (
id int,
age int
)engine=innodb;
 
insert into user_ex values(1,18);
insert into user_ex values(2,20);
insert into user_ex values(3,30);
insert into user_ex values(4,40);
insert into user_ex values(5,50);


一文讀懂“建立正確的索引,對(duì)數(shù)據(jù)庫(kù)性能提升的重要性”


explain select * from user,user_ex where user.id=user_ex.id;

如果id上不建索引,對(duì)于前表的每一行(row),后表都要被全表掃描。

今天這篇文章中,這個(gè)相同的join語(yǔ)句出現(xiàn)了三次:
(1)掃描類型為eq_ref,此時(shí)id為主鍵;
(2)掃描類型為ref,此時(shí)id為非唯一普通索引;
(3)掃描類型為ALL,全表掃描,此時(shí)id上無(wú)索引;
 
有此可見(jiàn),建立正確的索引,對(duì)數(shù)據(jù)庫(kù)性能的提升是多么重要。
 
另外,不正確的SQL語(yǔ)句,可能導(dǎo)致全表掃描。
 
全表掃描代價(jià)極大,性能很低,是應(yīng)當(dāng)極力避免的,通過(guò)explain分析SQL語(yǔ)句,非常有必要。


總結(jié)




(1)explain結(jié)果中的type字段,表示(廣義)連接類型,它描述了找到所需數(shù)據(jù)使用的掃描方式;
(2)常見(jiàn)的掃描類型有:
system>const>eq_ref>ref>range>index>ALL
其掃描速度由快到慢;
(3)各類掃描類型的要點(diǎn)是:

  • system最快:不進(jìn)行磁盤IO
  • const:PK或者unique上的等值查詢
  • eq_ref:PK或者unique上的join查詢,等值匹配,對(duì)于前表的每一行(row),后表只有一行命中
  • ref:非唯一索引,等值匹配,可能有多行命中
  • range:索引上的范圍掃描,例如:between/in/>
  • index:索引上的全集掃描,例如:InnoDB的count
  • ALL最慢:全表掃描(full table scan)

(4)建立正確的索引(index),非常重要;
(5)使用explain了解并優(yōu)化執(zhí)行計(jì)劃,非常重要;
 
思路比結(jié)論重要,希望大家有收獲。

畫外音:本文測(cè)試于MySQL5.6。


出處:架構(gòu)師之路(ID:road5858)


想了解更多關(guān)于數(shù)據(jù)庫(kù)、云技術(shù)的內(nèi)容嗎?

快來(lái)關(guān)注“數(shù)據(jù)和云”公眾號(hào)、“云和恩墨”官方網(wǎng)站,我們期待與大家一同學(xué)習(xí)和進(jìn)步!

一文讀懂“建立正確的索引,對(duì)數(shù)據(jù)庫(kù)性能提升的重要性”

(掃描上方二維碼,關(guān)注“數(shù)據(jù)和云”公眾號(hào),即可查看更多科技文章)

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI