讀懂MySQL執行計划


 

原文:https://mp.weixin.qq.com/s/-BlLvBKcF-yalELY7XkqaQ

 

前言

  在之前的面試過程中,問到執行計划,有很多童鞋不知道是什么?甚至將執行計划與執行時間認為是同一個概念。今天我們就一起來了解一下執行計划到底是什么?有什么用途?

執行計划是什么?

  執行計划,簡單的來說,是SQL在數據庫中執行時的表現情況,通常用於SQL性能分析,優化等場景。在MySQL中使用 explain 關鍵字來查看。如下所示:

1.查詢t_base_user
select * from t_base_user where name="andyqian";

2.查看上述語句的執行計划
explain select * from t_base_user where name="andyqian";

執行查看上述2語句后,我們可以得出以下執行計划

上面這個執行計划給到的信息是: 這是一個簡單的SQL,全表掃描,共掃描1行,Using where條件在t_base_user表中篩選出記錄。發現該語句並沒有走索引,為什么是這樣的呢?別急,我們緊接着看下一節。上面執行計划是什么意思呢?有什么參考價值呢?

讀懂執行計划

  通過上面,我們知道了什么是執行計划,也看到了執行計划到底是什么東西,現在我們來具體了解一下,MySQL執行計划中,每個屬性代表的是什么意思?

 我們一一來介紹,並說明每個屬性有哪些可選值,以及每個可選值的意思。

  • id: 表示查詢中select操作表的順序,按順序從大到依次執行

  • select_type :
    該表示選擇的類型,常見可選值有: SIMPLE(簡單的), PRIMARY(最外層) ,SUBQUERY(子查詢中的第一個select查詢)

  • type :
    該屬性表示訪問類型,有很多種訪問類型。
    最常見的其中包括以下幾種: ALL(全表掃描), index(索引掃描),range(范圍掃描),ref (非唯一索引掃描),eq_ref(唯一索引掃描,),(const)常數引用, 訪問速度依次由慢到快。

    其中 : range(范圍)常見與 between and ..., 大於 and 小於這種情況。
    提示 : 慢SQL是否走索引,走了什么索引,也就可以通過該屬性查看了。

  • table :
    表示輸出行數據所在表

  • possible_keys :
    顧名思義,該屬性給出了,該查詢語句,可能走的索引,(如某些字段上索引的名字)這里提供的只是參考,而不是實際走的索引,也就導致會有possible_Keys不為null,key為空的現象。

  • key : 顯示MySQL實際使用的索引,其中就包括主鍵索引(PRIMARY),或者自建索引的名字。

  • key_len : 表示索引所使用的字節數,

  • ref :
    連接匹配條件,如果走主鍵索引的話,該值為: const, 全表掃描的話,為null值

  • rows :
    掃描行數,也就是說,需要掃描多少行,采能獲取目標行數,一般情況下會大於返回行數。通常情況下,rows越小,效率越高, 大部分SQL優化,都是在減少這個值的大小。

    注意:  理想情況下掃描的行數與實際返回行數理論上是一致的,但這種情況及其少,如關聯查詢,掃描的行數就會比返回行數大大增加)

  • Extra 這個屬性非常重要,該屬性中包括執行SQL時的真實情況信息,如上面所屬,使用到的是"using where",表示使用where篩選得到的值,常用的有: "Using temporary": 使用臨時表 "using filesort": 使用文件排序

看到這里,我們應該已經發現,在第一步中,我們的這條SQL

select * from t_base_user where name="andyqian";

是沒有走索引的,而且還是全表掃描,在數據量少的情況下,問題還不會特別突出,如果數據量比較大,這可是個會造成生產事故的慢查詢哦,現在我們改造一下,將name字段添加上索引,

添加索引
alter table t_base_user add index idx_name(name);

看看它的執行計划是怎樣的。

你看,  現在已經走idx_name索引了,其type從All(全表掃描)到ref(非唯一索引了),別看就只有這一點點小區別,在大數據量的時候,可是會起至關重要的作用!

數據結構

  本文中演示的數據結構如下:

create table t_base_user(
oid bigint(20) not null primary key auto_increment,
name varchar(30) null comment "name",
email varchar(30) null comment "email",
age int null comment "age",
telephone varchar(30) null comment "telephone",
status tinyint(4) null comment "0 無效 1 有效",
created_at datetime null comment "",
updated_at datetime null comment ""
)
// 新增記錄:
insert into t_base_user (name,email,age,telephone,created_at,updated_at) values ("andyqian","andytohome",20,"15608411",now(),now();)

最后

  一個好的數據庫表設計,從一開始就應該考慮添加索引,而不是到最后發現慢SQL了,影響業務了,才來補救。其實我在工作經歷當中,由於新建表,或新加字段后,忘記添加索引也造成了多次生產事故,記憶猶新!!! 其實新建索引也是有一定的原則的,建什么索引,建在哪些字段上,這里面還有不少知識呢,下一篇文章寫,盡請期待吧!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM