MySQL 優化(二)(高階篇)

huxiaobai_001發表於2020-04-10

mysql效能優化

mysql的內部優化器介紹

mysql中有專門負責優化select語句的優化器模組,主要功能:通過計算分析系統中收集到的統計資訊,為客戶端請求的query提供他認為最優的執行計劃(他認為最優的資料檢索方式但不見得是DBA認為最優的,所以這部分最浪費時間)
我們通過某種方式獲取得知mysql低層是如何自動優化我們的sql的 那麼就更加便於我們對自己的sql語句進行優化

mysql常見的瓶頸在哪裡?

explain

使用explain關鍵字可以模擬優化器執行sql查詢語句,從而知道mysql是如何處理你的sql語句的。分析你的查詢語句或是表結構的效能瓶頸
explain + sql語句
執行計劃包含的資訊:

explain當中的ID

select查詢的序列號 包含一組數字 表示查詢中執行select子句或操作表的順序;
第一種情況:id相同 執行順序由上而下
sql案例:
explain select t2.* from t1,t2,t3 where t1.id=t2.id and t1.id =t3.id and t1.other_column=’’;
執行結果:

我們看到id都為1 table一欄表示操作表的執行順序 先操作哪個再操作哪個!
總結:id相同的時候 執行順序是由上而下的
比如:我們分析上邊的sql語句發現id都相同 那麼我們就去看table 執行順序就是從上到下執行的 t1 t3 t2的順序
第二種情況:id不同,如果是子查詢,id的序號會遞增,id值越大優先順序越高越先被執行
sql案例:
explain select t2.* from t2 where id = (
select id from t1 where id = (
select t3.id from t3 where t3.other_column = ‘’
)
);
執行結果:

我們看到id的編號是不同的 完全不同! table一欄也是表示的執行順序 就是先操作哪個再操作哪個表的意思
總結:id完全不同的時候如果是子查詢 id的序號會遞增 id越大優先順序越高越先被執行 (一般會先執行括號裡面的 一層括號一層括號的往外執行)
比如:我們通過分析上邊的sql, id都不相同 那麼我們就去看table欄 id越大的執行優先順序越高 順序也就是t3 t1 t2
第三種情況:id相同又不同的情況(就是有幾個是相同的 其他的又不同)
sql案例:
explain select t2.* from (
select t3.id from t3 where t3.other_column = ‘’)s1,t2 where s1.id = t2.id;
注意:from後邊是一張虛擬表
執行結果:

我們發現id有相同的也有不同的 這種情況下如何分析呢 我們可以把id相同的看成一組 其他的相同的都各自為一組 在所有的組當中,id值越大 優先順序越高 越先執行 所以這裡id=2的是最大的 也就是t3表先被執行 然後在看相同的為一組 id = 1的這一組 那麼執行順序就是從上往下的 所以 再執行 最後執行的是t2!
我們可以能會好奇怎麼會有表呢?derived是衍生的意思 也就是sql當中的s1 s1是由id=2的對應的table也就是t3衍生出來的!看sql就能看出來啊!
總結:我們發現id有相同的有不同的 id相同的我們可以理解成一組 是從上往下執行的 id不同的是單獨一組 在所有的組當中,id值越大 優先順序越高 越先執行

explain當中的select_type含義介紹:

explain當中的table的含義介紹:

顯示這一行的資料是關於哪張表的

explain當中的type的含義介紹:

如果沒有建立索引 那麼通過explain檢視到的type都是all全表掃描 所以對於大資料量查詢的話 where後邊的最好加上索引 我是說大資料量 上百萬 千萬級別 甚至上億

explain當中type各個引數的解釋:

type顯示的是訪問型別 是較為重要的一個指標 結果的值從最好到最壞依次是:
system > const > eq_erf > ref > range > index > all
一般情況下 得保證查詢至少能達到range級別 最好能達到ref級別
system級別:
表只有一行記錄(等於系統表),這是const型別的特例 平時不會出現 這個也可以忽略不計(注意:實際開發當中沒有哪個複雜的邏輯和架構是單行單列的 不用考慮這個了)
const級別:
表示通過索引一次就找到了,const用於比較primary_key或者unique索引。因為只匹配一行資料 所以很快。如將主鍵配置於where列表當中了,mysql就能將該查詢轉換成一個常量
(注意:實際開發當中查詢一行沒必要進行優化 所以我們對它的關注度也不用太高!)

eq_ref級別:
唯一性索引掃描 對於每個索引鍵 表中只有一條記錄與之匹配 常見於主鍵或者唯一索引掃描;比如給身份賬號設定了唯一索引 那麼我們在where條件後邊加上身份證號=‘’那麼就會出現eq_ref級別
(注意:用到了索引 並且是唯一索引或者主鍵)
ref級別:
非唯一性索引掃描,返回匹配某個單獨值的所有行。本質上也是一種索引訪問,它返回所有匹配某個單獨值的行,然而他可能會找到多個符合條件的行,所以他應該屬於查詢和掃描的混合體!
比如我們要查詢java部門的員工 我們要查詢的是員工 員工有可能重名所以不能建立唯一索引 可能我們會建立個普通的單值索引 那麼查詢出來的記錄會有很多 因為一個部門下會有很多員工啊!那麼這條sql語句的級別就是在ref級別!
(注意:沒有用到唯一性索引 但是可能會用到普通單值索引或者符合索引)
range級別:
只檢索給定範圍的行,使用一個索引來選擇行,key列顯示使用了哪個索引 一般就是在你的where語句中出現了between < > in等的查詢 這種範圍掃描索引比全表掃描要好,因為它只需要開始於索引的某一點而結束語另外一點 不用掃描全部索引;
index級別:
full index scan index於all區別為index型別只遍歷索引樹 這通常比all快 因為索引檔案通常比資料檔案小 也就是說雖然all和index都是度全表 但是index是從索引中讀取 而all是從硬碟中讀取的

all級別:
full table scan 將遍歷全表以找到匹配的行 如果資料在百萬級別或者千萬級別的 發現存在all級別 那麼我們就有必要採取sql的優化措施了!

本作品採用《CC 協議》,轉載必須註明作者和本文連結

胡軍

相關文章