久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

MySQL 5.7Explain執行計劃

132次閱讀
沒有評論

共計 6468 個字符,預計需要花費 17 分鐘才能閱讀完成。

自動寫代碼機器人,免費開通

丸趣 TV 小編給大家分享一下 MySQL 5.7Explain 執行計劃,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

目錄

1. 介紹

2. Explain 結果列詳解

2.1 id

2.2 select_type

2.3 table

2.4 partitions

2.5 type(非常重要)

2.6 possible_keys

2.7 key

2.8 key_len

2.9 ref

3.10 rows

2.11 filtered

2.12 Extra

【注】

當前系統環境:MySQL 5.7,其他版本略有不同,后期會抽時間單獨說明。

只介紹常見的場景,其他少見的場景暫不研究,如有需要可以去官方文檔中查找。

非入門,需要對 MySQL 的底層數據結構 B+ 樹有一定的了解。

文檔參考:
MySQL 官方 Explain 文檔

1. 介紹

使用 EXPLAIN 關鍵字可以模擬優化器執行 SQL 語句,并分析查詢語句的性能瓶頸。

2. Explain 結果列詳解

2.1 id

id 列的編號是 select 的序列號,一般有幾個 select 就有幾個 id(聯表查詢會有重復的 id),并且 id 的順序是按 select 出現的順序增長的。

id 越大則表示執行的優先級越高,id 相同(一般出現在聯表查詢)則從上往下執行,id 為 NULL 最后執行。

2.2 select_type

select_type 表示對應行是簡單的還是復雜的查詢。常見的值有:

simple:簡單查詢,查詢不包含子查詢和 union。

primary:復雜查詢中最外層的 select。

subquery:包含在 select 中的子查詢(不在 from 子句中)

derived:包含在 form 子句中的子查詢,MySQL 會將結果放在一個臨時表中,也稱為派生表。

union:在 union 中的第二個或之后的 select。

【注】在 MySQL 5.7 中,會對衍生表進行合并優化,如果要直觀的查看 select_type 的值,需要臨時關閉該功能(默認是打開的),下面的介紹中凡是涉及到衍生表的都需要該操作。

#  關閉衍生表的合并優化(只對該會話有效)set session optimizer_switch= derived_merge=off  #  打開衍生表的合并優化(只對該會話有效)set session optimizer_switch= derived_merge=on

2.3 table

對應行查詢的表。

【注】

當 from 子句中有子查詢時,table 列為是 derivenN 的格式,表示這一行的執行的是 id = N 行的查詢。

當有 union 時,table 的數據為 union M,N 的格式,M 和 N 表示參與 union 的 select 行 id。

2.4 partitions

未完待續。。。

2.5 type(非常重要)

type 表示這行查詢的關聯類型(訪問類型,或查詢類型),通過該值可以了解該行查詢數據記錄的大概范圍。

常見的值依次從最優到最差分別為:system const eq_ref ref range index ALL;一般我們要保證效率的話,要優化我們的語句至少使其達到 range 級別,如果可能的話做好優化到 ref;range 一般用于范圍查找,所以換句話說除了范圍查找,其他的查詢語句我們最好是優化到 ref 級別。

常見值說明:

NULL : 表示 MySQL 能夠在優化階段分解查詢語句,在執行階段不用訪問表和索引。

system / const:MySQL 能對某個查詢部分進行優化并將其轉化成一個常量(可以通過 show warnings 查看優化的結果),主要是查詢主鍵(Primary Key)或唯一鍵索引(Unique Key)對應的記錄,因為不存在重復,所以最多只能查詢出一條記錄,所以速度比較快。system 是 const 的特例,當臨時表里只有一條記錄時為 system。

#  表里有一個主鍵 id 為 1 的記錄  - constexplain select * from student where id = 1#  派生表里面只有一條記錄  - systemexplain select * from (select * from student where id = 1) tmp#  注:  如果查詢的列中有  text  類型,那么在這里  type  會變為  ALL ,#  因為無法使用內存臨時表,只能在磁盤上創建臨時表,所以性能上會有所損耗,效果等同于全表查詢  ALL。

req_ref:當主鍵或唯一鍵索引的相關列并聯接使用時(聯表查詢),最多匹配一條符合條件的記錄。這是除了 const 之外的最好的聯接類型,簡單的 select 查詢不會出現 req_ref,更多出現在聯表查詢。

#  雖然返回結果中有多條記錄,但是在查詢中一個學生 id 只對應一個班級,所以查詢班級的時候為  req_ref,#  但是查詢  student  的時候是  ALL,全表查詢 explain select * from student left join banji on student.id = banji.student_id

【注】在查詢的過程中的返回結果如下:
MySQL 5.7Explain 執行計劃
當聯接表查詢時候會看作是一條查詢 SQL,所以它們對應的 id 是一樣的,當 id 都是一樣的時候,按照從上到下的順序依次執行,這里是先查詢班級所有的學生(全表查詢 ALL),然后根據學生 id 查找出學生對應的班級信息(req_ref)。

ref:當使用普通索引(Normal)或者是聯合索引的部分前綴時,索引要和某個值進行比較,可能會找到多個符合條件的記錄行,從輔助索引的根節點開始對比并找到相應的記錄。

#  簡單的  select  查詢,name  是普通索引(Normal Index)explain select * from student where name =  張三 #  簡單  select  查詢,banji_id (第一個)  和  student_id (第二個)  的聯合索引 EXPLAIN SELECT * FROM banji_student WHERE banji_student.banji_id = 3#  關聯表查詢 #  包含  banji  表,banji_student  是班級與學生的關系表#  關系表中有  banji_id (第一個)  和  student_id (第二個)  的聯合索引  idx_banji_stu_id  索引,#  以下查詢只用到了聯合索引的  banji_id (第一個)explain select * from banji_id from banji left join banji_student 
 on banji.id = banji_student.banji_id

range:范圍掃描,通常出現在 in,between,,,= 等操作中,使用一個索引來檢索給定范圍的行。

#  查詢  id  大于  1  的學生信息 explain select * from student where id   2;

index:

# student  表只有 id 主鍵,name  普通索引 select * from student;#  這個時候會走  name  索引 #  因為  name  是普通索引,所以如果加  where  的話可以達到  ref  級別 select * from student where name =  Ana

覆蓋索引定義:覆蓋索引一般針對于輔助索引,并不是真正的索引,只是索引查找的一種方式。如果 select 查詢的字段都在輔助索引樹中全部拿到,這種情況一般是使用了覆蓋索引,不需要通過輔助索引樹找到主鍵,再通過主鍵去主鍵索引樹里獲取其它字段值。

掃描全索引就能拿到結果,一般是掃描某個二級索引(輔助索引,除了主鍵之外的索引)。這種索引不會從主鍵索引樹根節點開始查找,而是直接對二級索引的葉子節點遍歷和掃描,從而查找出相應的記錄行,速度比較慢;

這種查詢方式一般為使用覆蓋索引,查詢所需的所有結果集在二級索引與主鍵索引中都有的情況下,由于二級索引一般比較小(因為二級索引是非聚集的,其葉子節點是存放的主鍵索引相應的地址,而主鍵索引是聚集的,其葉子節點存放的是完整的數據集),所以優先走二級索引,這種情況通常比 ALL 快一些。

在某些情況下,如果表的列數特別多,這個時候通過輔助索引查詢的性能就不如直接使用主鍵索引效率高(如果查詢了輔助索引的話,還會返回到主鍵索引中進行查找更多的字段,也就是回表查詢,當然在某些情況下使用回表查詢的性能也會比只使用主鍵索引的性能高),這個時候會走主鍵索引,這種情況也比 ALL 快。

ALL:全表掃描,掃描主鍵(聚簇、聚集)索引樹的所有葉子節點,通常這種情況下要根據業務場景來增加其他索引進行優化。

# id  為主鍵的  student  表,沒有其他索引,該查詢為  ALL.select * from student

2.6 possible_keys

possible_keys 主要顯示查詢可能用到哪些索引來查找,只是可能會使用,并不代表一定會使用。

常見值說明:

NULL: 沒有相關索引,如果是 NULL 的話,可以考慮在 where 子句中創建一個適當的索引來提高查詢性能,然后繼續用 explain 查看其效果;也有可能出現 possible_keys 為 NULL,但是 key 有值,實際走了索引。

有列值:如果顯示表中的某列,則表示可能會走這一列對應列值的索引;如果 possible_keys 有值,但是 key 顯示 NULL,這種情況一般存在于表中數據量不大的情況,因為 MySQL 語句優化器認為索引對此查詢的幫助不大,從而選擇了全表查詢。

2.7 key

key 表示 MySQL 實際采用哪個索引來優化對該表的查詢。

如果沒有使用索引,則該列為 NULL,如果想強制 MySQL 使用或忽略 possible_keys 列中的索引,可以在查詢中使用 force index 或 ignore index.

2.8 key_len

顯示了 MySQL 索引所使用的字節數,通過這個數值可以計算具體使用了索引中的哪些列(主要用于聯合索引的優化)。

【注】索引最大長度是 768 字節,當字符串過長時,MySQL 會做一個類似左前綴索引的處理,將前半部分的字符提取出來做索引。

示例:一個學生與班級的關系表:banji_student,存在使用 banji_id 與 student_id 兩個列組合的聯合索引,并且每個索引 int 都是 4 字節,通過 key_len 值為 4 可以知道只使用了聯合索引的第一列:banji_id 來執行索引查找。

#  只使用了聯合索引的第一列 select * from banji_student where banji_id = 2

key_len 的計算規則如下:

字符串:常見的是 char(n) 和 varchar(n),從 MySQL 5.0.3 之后,n 均表示字符數,而不是字節數,如果是 UTF-8,一個數字或字母占 1 個字節,一個漢字占 3 個字節。

描述 char(n) 非漢字長度為 n,如果存放漢字長度為 3n 字節 varchar(n) 非漢字長度為 n+2,如果存放漢字長度為 3n+2 字節;因為 varchar 是可變長字符串,需要 2 字節來存儲字符串長度

數值類型:

描述 tinyint 長度為 1 字節 smallint 長度為 2 字節 int 長度為 4 字節 bigint 長度為 8 字節

時間類型:

描述 date 長度為 3 字節 timestamp 長度為 4 字節 datetime 長度為 8 字節

NULL

如果字段允許設置為 NULL,則需要 1 字節來記錄是否為 NULL;Not NULL 的列則不需要。

2.9 ref

顯示了在使用 key 列中實際的索引時,表查找時所用到的列名和常量;常見的為 const 常量或索引關聯查詢的字段(列)名。

#  使用了常量  2,所以在查詢的時候  ref  為  constselect * from student where id = 2#  關聯表查詢 #  包含  banji  表,banji_student  是班級與學生的關系表#  關系表中有  banji_id (第一個)  和  student_id (第二個)  的聯合索引  idx_banji_stu_id  索引#  這里的  ref  為  test.id ,也就是指的是  banji.idexplain select * from banji_id from banji left join banji_student  on banji.id = banji_student.banji_id

3.10 rows

顯示預計查詢的結果數,并不是真正的結果集中的記錄(行)數,僅供參考。

2.11 filtered

未完待續。。。

2.12 Extra

這一列展示的是額外的信息,存在很多值,且在不同的場景下以及不同版本的 MySQL 所表示的意思也不同,只能是表示大概的意思并且僅做優化參考,這里只介紹常見的值。

Using index:使用覆蓋索引,在 type 相同的情況下,Extra 的值為 Using index 要比為 NULL 性能高。

比如 banji 表,存在 id,name,create_time 列,存在 id 主鍵與 name 普通索引。

#  覆蓋索引,直接查詢  name  對應的索引樹就可以滿足  select  后面的查詢列 select id,name from banji#  非覆蓋索引,雖然也走了索引,但是進行了回表查詢,以查詢出  create_time  字段。select * from banji where name =  二年級 

Using where:使用 where 關鍵字來查詢,并且對應的列沒有設置索引,對應的 key 為 NULL。

這種情況一般要對查詢的列添加相對應的索引來進行優化。

Using index condition:非覆蓋索引查詢并進行了回表,并且輔助索引使用了條件查詢語句(where 或其他)。

比如 banji_student 關系表,存在 id,banji_id,student_id,create_time 列,存在 id 主鍵 和 banji_id 與 student_id 的組合(聯合)索引。

#  進行了回表查詢,以查詢出  create_time  列,并且組合索引進行了范圍查找 select * from banji_student where banji_id   3

Using temporary:MySQL 需要創建創建一個臨時表來處理查詢,出現這種情況一般要添加索引進行優化處理。

#  如果  name  沒有添加普通索引的話,則需要創建一個臨時表來進行去重,Extra  值為  Using temporary#  如果添加了索引,則會走  name  對應的索引樹,并且是覆蓋索引,Extra  值為  Using indexexplain select distinct name from student

Using filesort:使用外部排序而不是索引排序,當數據較小的時候采用的是內存排序,當數據量較大的時候會頻繁的訪問磁盤,并將排序后的數據寫入磁盤。

#  如果  name  沒有添加普通索引的話,則需要創建一個臨時表來進行去重,Extra  值為  Using filesort#  如果添加了索引,則會走  name  對應的索引樹,并且是覆蓋索引,Extra  值為  Using indexexplain select name from student order by name

Select tables optimized away:使用聚合函數(例如 max、min 等)來訪問存在索引的字段時,只訪問索引樹中已排好序的葉子,節點性能很高。

#  比如使用聚合函數  min  查詢最小的學生  id(主鍵)explain select min(id) from student

以上是“MySQL 5.7Explain 執行計劃”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注丸趣 TV 行業資訊頻道!

向 AI 問一下細節

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-12-16發表,共計6468字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 秦皇岛市| 高淳县| 轮台县| 西充县| 喀喇沁旗| 修水县| 垦利县| 遂溪县| 荣昌县| 射阳县| 彭阳县| 连江县| 油尖旺区| 星子县| 镇宁| 连城县| 蓝山县| 吐鲁番市| 林口县| 苍溪县| 镇原县| 大化| 锡林郭勒盟| 陆丰市| 武穴市| 吉首市| 新野县| 汉寿县| 肇东市| 张北县| 平山县| 雷波县| 孝昌县| 鄂托克前旗| 卓资县| 白山市| 普定县| 娄烦县| 湘潭市| 托里县| 商都县|