1. 程式人生 > >MySQL_explain關鍵字分析查詢語句

MySQL_explain關鍵字分析查詢語句

  通過對查詢語句的分析,可以瞭解查詢語句的執行情況。MySQL中,可以使用EXPLAIN語句和DESCRIBE語句來分析查詢語句。

  EXPLAIN語句的基本語法如下:(DESCRIBE語法一致,DESCRIBE可簡寫為DESC)

  EXPLAIN Select 語句;

  eg:explain SELECT * FROM `user` where name = 'name6'; 結果如下:

 

  explain結果值及其含義:

引數值

含義

id

表示SELECT語句的編號;

select_type

表示SELECT語句的型別。

該引數有幾個常用的取值:

SIMPLE   :表示簡單查詢,其中不包括連線查詢和子查詢;

PRIMARY:表示主查詢,或者是最外層的查詢語句;

UNION    :表示連線查詢的第二個或後面的查詢語句;

table

表示查詢的表;

type

表示表的連線型別。該引數有幾個常用的取值:

const   :表示表中有多條記錄,但只從表中查詢一條記錄;

eq_ref :表示多表連線時,後面的表使用了UNIQUE或者PRIMARY KEY;

ref       :表示多表查詢時,後面的表使用了普通索引;

unique_ subquery:表示子查詢中使用了UNIQUE或者PRIMARY KEY;

index_ subquery:表示子查詢中使用了普通索引; range  :表示查詢語句中給出了查詢範圍;

index   :表示對錶中的索引進行了完整的掃描;

all        :表示此次查詢進行了全表掃描; ----------- 該條SQL需要優化;

possible_keys

表示查詢中可能使用的索引;

如果備選的數量大於3那說明已經太多了,因為太多會導致選擇索引而損耗效能, 所以建表時欄位最好精簡,同時也要建立聯合索引,避免無效的單列索引;

key

表示查詢使用到的索引;

key_len

表示索引欄位的一長度;

ref

表示使用哪個列或常數與索引一起來查詢記錄;

rows

表示查詢的行數;

試圖分析所有存在於累計結果集中的行數,雖然只是一個估值,卻也足以反映 出SQL執行所需要掃描的行數,因此這個值越小越好;

Extra

表示查詢過程的附件資訊。

  通過explain可以得到如下結論:

  ①使用索引比未使用索引,掃描的行數更少查詢速度更快;

  ②在查詢語句中使用LIKE關鍵字進行查詢時,如果匹配字串的第一個字元為“%”時,索引不會被使用。如果“%”不是在第一個位置,索引就會被使用。

  ③使用多列索引時只有查詢條件中使用了該索引中的第一個索引欄位時,索引才會被使用。

  注:create index index_age_sex on user(age,sex);  age為第一個索引;

  ④查詢語句只有OR關鍵字時,如果OR前後的兩個條件列都是索引時,查詢中將使用索引。只要OR前後有一個條件的列不是索引,那麼查詢中將不使用索引。

  注: 1:where 語句裡面如果帶有or條件, myisam表能用到索引,innodb不行;2:必須所有的or條件都必須是獨立索引;

  以上結論來自如下測試:

user表: 獨立索引:id、name 聯合索引:age && sex

user_noindex表: 無任何索引列;

CREATE TABLE `user` (   `id` int(11) NOT NULL,   `name` varchar(30) NOT NULL,   `age` int(11) NOT NULL,   `sex` tinyint(4) NOT NULL,   `isDeleted` tinyint(4) NOT NULL,   PRIMARY KEY (`id`),   UNIQUE KEY `id_unidx` (`id`) USING BTREE,   UNIQUE KEY `name_unidx` (`name`) USING BTREE,   KEY `index_age_sex` (`age`,`sex`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `user_noindex` (   `id` int(11) NOT NULL,   `name` varchar(30) NOT NULL,   `age` int(11) DEFAULT NULL,   `sex` tinyint(4) DEFAULT NULL,   `isDeleted` tinyint(4) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  【1】索引對查詢的影響-----加索引和不加索引的對比-----使用索引掃描的更少查詢更快

    語句1:explain SELECT * FROM `user` where name = 'name6';

  語句2:explain SELECT * FROM `user_noindex` where name = 'name6';

結果集 id select_type table type possible_keys key key_len ref rows Extra
語句1 1 SIMPLE user const name_unidx name_unidx 32 const 1 null
語句2 1 SIMPLE user_noindex ALL null null null null 10 Using where

  【2】索引對查詢的影響-----加索引----使用和未使用索引的對比-----在查詢語句中使用LIKE關鍵字進行查詢時,如果匹配字串的第一個字元為“%”時,索引不會被使用。如果“%”不是在第一個位置,索引就會被使用。  

  語句1:explain SELECT * FROM `user` where name like '%name6';

  語句2:explain SELECT * FROM `user` where name like '%name6%';

  語句3:explain SELECT * FROM `user` where name like 'name6%';

結果集 id select_type table type possible_keys key key_len ref rows Extra
語句1 1 SIMPLE user ALL null null null null 10 Using where
語句2 1 SIMPLE user ALL null null null null 10 Using where
語句3 1 SIMPLE user range name_unidx name_unidx 32 const 1 null

【3】索引對查詢的影響-----加索引----使用和未使用索引的對比-----多列索引是在表的多個欄位建立一個索引。只有查詢條件中使用了這個欄位中的第一個欄位時,索引才會被使用。

  語句1:explain SELECT * FROM `user` where age  = '19';

  語句2:explain SELECT * FROM `user` where sex  = '1';

  語句3:explain SELECT * FROM `user` where sex = '1' and age  = '19';

結果集 id select_type table type possible_keys key key_len ref rows Extra
語句1 1 SIMPLE user ref index_age_sex index_age_sex 4 const 1 null
語句2 1 SIMPLE user ALL null null null null 10 Using where
語句3 1 SIMPLE user ref index_age_sex index_age_sex 5 const,const 1 null

【4】索引對查詢的影響-----加索引----使用和未使用索引的對比-----查詢語句只有OR關鍵字時,如果OR前後的兩個條件的列都是索引時,查詢中將使用索引。如果OR前後有一個條件的列不是索引,那麼查詢中將不使用索引。

  語句1:explain SELECT * FROM `user` where (age  = '19' OR isDeleted = '0'); 

  語句2:explain SELECT * FROM `user` where (sex = '1' OR age  = '19');  -- 聯合索引

  語句3:explain SELECT * FROM `user` where (name = 'name1' OR id  = '1'); -- 獨立索引

  -- alter table user engine = innodb;

結果集 id select_type table type possible_keys key key_len ref rows Extra
語句1 1 SIMPLE user ALL index_age_sex null null null 10 Using where
語句2 1 SIMPLE user ALL index_age_sex null null null 10 Using where
語句3 1 SIMPLE user ref PRIMARY,id_unidx,name_unidx index_age_sex null null 10 Using where

  -- alter table user engine = myisam;

結果集 id select_type table type possible_keys key key_len ref rows Extra
語句1 1 SIMPLE user ALL index_age_sex null null null 10 Using where
語句2 1 SIMPLE user ALL index_age_sex null null null 10 Using where
語句3 1 SIMPLE user index_merge PRIMARY,
id_unidx,
name_unidx
name_unidx,
PRIMARY
32,4 null 2 Using union
(name_unidx,PRIMARY);
 Using where

  很多查詢中需要使用子查詢。子查詢可以使查詢語句很靈活,但子查詢的執行效率不高。子查詢時,MySQL需要為內層查詢語句的查詢結果建立一個臨時表。然後外層查詢語句在臨時表中查詢記錄。查詢完畢後,MySQL需要撤銷這些臨時表。因此,子查詢的速度會受到一定的影響。如果查詢的資料量比較大,這種影響就會隨之增大。在MySQL中可以使用連線查詢來替代子查詢。連線查詢不需要建立臨時表,其速度比子查詢要快。