1. 程式人生 > 其它 >mysql 建立materialized檢視_MySQL執行計劃

mysql 建立materialized檢視_MySQL執行計劃

技術標籤:mysql 建立materialized檢視

MySQL執行計劃

我們經常使用 MySQL 的執行計劃來檢視 SQL 語句的執行效率,接下來分析執行計劃的各個顯示內容。

EXPLAIN
SELECT
    ( SELECT t2.NAME FROM tb_dept t2 WHERE t2.id = t1.dept_id ) 
FROM
    tb_user t1,
    tb_user_role t3,
    tb_role t4 
WHERE t1.id=t3.user_id
    AND t3.role_id = t4.id
    AND t4.name='開發部'

863e0000ff8a46d49f0cc037be01a53f.png

執行計劃的 id

select 查詢的序列號,標識執行的順序

  • id相同,執行順序由上至下
  • id不同, 如果是子查詢,id 的序號會遞增,id 值越大優先順序越高,越先被執行

執行計劃的 select_type

  • SIMPLE:簡單的 select 查詢,查詢中不包含子查詢或者UNION
  • PRIMARY:為複雜查詢建立的首要表(也是最外層的表) 這種型別通常與DERIVED 或者 UNION 混合使用見到
  • UNION: 當SELECT 之前的關鍵字為UNION 或 UNION ALL時 會出現UNION 關鍵字
  • DEPENDENT UNION: 當子查詢中存在UNION時UNION 後的 select_type 會出現 DEPENDENT UNION 而union 語句的第一行為 DEPENDENT SUBQUERY
  • UNION RESULT: 出現在UNION 或UNION ALL語句中 代表把所有結果集聯合起來
  • SUBQUERY:出現在複雜非相關子查詢中 ,簡單相關子查詢MySQL會進行改寫
  • DEPENDENT SUBQUERY: 出現在相關子查詢中而非相關子查詢MySQL可以進行改寫
  • DERIVED: 衍生表當查詢使用內聯檢視時會出現此關鍵字
  • MATERIALIZED: 子查詢物化 ,當表出現在非相關子查詢中並且需要進行物化時會出現MATERIALIZED關鍵詞
  • UNCACHEABLE SUBQUERY:表示子查詢不可被物化需要逐次執行
  • UNCACHEABLE UNION: 子查詢中出現UNION並且不可被快取在UNION 後的 SELECT 語句出現此關鍵詞

執行計劃的 table

查詢涉及到的表。

  • 直接顯示錶名或者表的別名
  • <union M,N> 由 id 為 M,N 查詢 union 產生的結果
  • <subqueryN> 由 id 為 N 查詢產生的結果

執行計劃的 partitions

表分割槽、表建立的時候可以指定通過那個列進行表分割槽。

create table tmp (
  id   int unsigned not null AUTO_INCREMENT,
  name varchar(20),
  PRIMARY KEY (id)
)engine = innodb partition by key (id) partitions 5;

2246a889c46a7710f79e00b426208cc1.png

執行計劃的 type

訪問型別,SQL 查詢優化中一個很重要的指標,結果值從好到壞依次是:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

一般常用和需要重點關注的 system > const > eq_ref > ref > range > index > ALL。

  • system:系統表,少量資料,不進行磁碟IO,這是 const 型別的特列,平時不會出現,這個也可以忽略不計
  • const: PK 或者 unique 上的等值查詢
  • eq_ref: PK 或者 unique 上的 join 查詢,等值匹配,對於前表的每一行,後表只有一行命中
  • ref: 非唯一索引,等值匹配,可能有多行命中
  • range: 索引上的範圍掃描,例如:between、in、>
  • index:索引樹掃描, 例如:Innodb 的 count
  • ALL: 全表掃描(full table scan)

執行計劃的 possible_keys

查詢過程中有可能用到的索引。(不重要)

執行計劃的 key

實際使用的索引,如果為 NULL ,則沒有使用索引 。

執行計劃的 key_len

key_len 表示索引使用的位元組數,根據這個值就可以判斷索引使用的情況。特別是在組合索引的時候,判斷索引的索引欄位是否都被查詢到。那麼key_len是怎麼計算的呢,計算方法如下:

1. 整數型別,浮點數型別,時間型別的索引長度

NOT NULL = 欄位本身的欄位長度

NULL = 欄位本身的欄位長度+1,因為需要有是否為空的標記,這個標記需要佔用1個位元組

datetime = datetime不存毫秒的情況下是5個位元組,存毫秒的情況下是8個位元組

2.字元型別

varchr(n)變長欄位且允許NULL    =  n * (utf8=3,gbk=2,latin1=1)+1(NULL)+2
varchr(n)變長欄位且不允許NULL  =  n * (utf8=3,gbk=2,latin1=1)+2

char(n)固定欄位且允許NULL      =  n * (utf8=3,gbk=2,latin1=1)+1(NULL)
char(n)固定欄位且不允許NULL    =  n * (utf8=3,gbk=2,latin1=1)

變長欄位需要額外的2個位元組(VARCHAR值儲存時只儲存需要的字元數,另加一個位元組來記錄長度(如果列宣告的長度超過255,則使用兩個位元組),所以VARCAHR索引長度計算時候要加2),固定長度欄位不需要額外的位元組。

而NULL都需要1個位元組的額外空間,所以索引欄位最好不要為NULL,因為NULL讓統計更加複雜並且需要額外的儲存空間。

複合索引有最左字首的特性,如果複合索引能全部使用上,則是複合索引欄位的索引長度之和,這也可以用來判定複合索引是否部分使用,還是全部使用。下面舉個例子:

DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `id` bigint NOT NULL AUTO_INCREMENT ,
  `username` varchar(10) NOT NULL ,
  `password` varchar(20) NOT NULL ,
  `name` varchar(10) NOT NULL ,
  `idCard` char(10) DEFAULT NULL ,
  `age` int NOT NULL ,
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_user` (`name`,`idCard`,`age`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;

EXPLAIN SELECT * FROM users WHERE name='admin' AND idcard='1234' AND age = 20;

name 型別為 varchar,長度為10

idcard 型別為 char, 長度為10,可為空

age 型別為 int

字符集型別 utf8

key_len = ( 10 * 3 + 2 ) + (10 * 3 + 1 ) + 4 = 67

c526ebeec69ec011d964f6304296a424.png

執行計劃的 ref

表示上述表的連線匹配條件,即哪些列或常量被用於查詢索引列上的值

執行計劃的 rows

根據表統計資訊或者索引選用情況,大致估算出找到所需的記錄所需要讀取的行數。

執行計劃的 filtered

表示返回結果的行數佔需讀取行數的百分比, filtered 的值越大越好。

執行計劃的 Extra

十分重要的額外資訊。

  • Using filesort:MySQL 對資料使用一個外部的檔案內容進行了排序,而不是按照表內的索引進行排序讀取。
  • Using temporary:使用臨時表儲存中間結果,也就是說 MySQL 在對查詢結果排序時使用了臨時表,常見於 order by 或 group by。
  • Using index:表示 SQL 操作中使用了覆蓋索引(Covering Index),避免了訪問表的資料行,效率高。
  • Using index condition:表示 SQL 操作命中了索引,但不是所有的列資料都在索引樹上,還需要訪問實際的行記錄。
  • Using where:表示 SQL 操作使用了 where 過濾條件。
  • Select tables optimized away:基於索引優化 MIN/MAX 操作或者 MyISAM 儲存引擎優化 COUNT(*) 操作,不必等到執行階段再進行計算,查詢執行計劃生成的階段即可完成優化。
  • Using join buffer (Block Nested Loop):表示 SQL 操作使用了關聯查詢或者子查詢,且需要進行巢狀迴圈計算。MySQL執行計劃