MySQL 索引 explain索引分析優化

EXPLAIN是MySQL提供的工具,可用於模擬優化器執行SQL查詢語句,從而知道MySQL是如何處理SQL語句的,包括表的讀取順序、數據讀取操做的操做類型、可能使用的索引、實際使用的索引、表之間的引用、每張表有多少行數據被優化器查詢等。藉助於EXPLAIN,能夠知道何時必須爲表加入索引能夠獲得一個使用索引來尋找記錄的更快的SELECT。mysql

eg:sql

create table tbl_ta(ida int ,txt varchar(20),primary key(ida));緩存

insert into tbl_ta values (1,'AAAAA');服務器

create table tbl_tb(idb int ,txt varchar(20),primary key(idb));函數

insert into tbl_tb values (1,'BBBBB');工具

create table tbl_tc(idc int ,txt varchar(20),primary key(idc));oop

insert into tbl_tc values (1,'CCCCC');大數據

mysql> explain優化

    -> SELECT tbl_tb.*spa

    ->   FROM tbl_tb

    ->  WHERE idb =

    ->        (SELECT ida

    ->           FROM tbl_ta

    ->          WHERE ida = (SELECT idc FROM tbl_tc WHERE txt = 'CCCCC'));

+----+-------------+--------+-------+---------------+---------+---------+-------+------+-------------+

| id | select_type | table  | type  | possible_keys | key     | key_len | ref   | rows | Extra       |

+----+-------------+--------+-------+---------------+---------+---------+-------+------+-------------+

|  1 | PRIMARY     | tbl_tb | const | PRIMARY       | PRIMARY | 4       | const |    1 | NULL        |

|  2 | SUBQUERY    | tbl_ta | const | PRIMARY       | PRIMARY | 4       | const |    1 | Using index |

|  3 | SUBQUERY    | tbl_tc | ALL   | NULL          | NULL    | NULL    | NULL  |    1 | Using where |

+----+-------------+--------+-------+---------------+---------+---------+-------+------+-------------+

3 rows in set (0.00 sec)

mysql> explain extended SELECT tbl_tb.*

    ->   FROM (SELECT idc FROM tbl_tc WHERE txt = 'CCCCC') t1, tbl_tb

    ->  WHERE t1.idc = tbl_tb.idb ;

+----+-------------+------------+------+---------------+-------------+---------+-------------------+------+----------+-------------+

| id | select_type | table      | type | possible_keys | key         | key_len | ref               | rows | filtered | Extra       |

+----+-------------+------------+------+---------------+-------------+---------+-------------------+------+----------+-------------+

|  1 | PRIMARY     | tbl_tb     | ALL  | PRIMARY       | NULL        | NULL    | NULL              |    1 |   100.00 | NULL        |

|  1 | PRIMARY     | <derived2> | ref  | <auto_key0>   | <auto_key0> | 4       | sakila.tbl_tb.idb |    2 |   100.00 | Using index |

|  2 | DERIVED     | tbl_tc     | ALL  | NULL          | NULL        | NULL    | NULL              |    1 |   100.00 | Using where |

+----+-------------+------------+------+---------------+-------------+---------+-------------------+------+----------+-------------+

3 rows in set, 1 warning (0.00 sec)

EXPLAIN各字段的業務含義:

項(列明)

可選的值

業務說明

id 查詢序列號

一、2....

MySQL Query Optimizer 選定的執行計劃中查詢的序列號。表示查詢中執行 select 子句或操做表的順序。id 值越大優先級越高,越先被執行,id 相同執行順序由上至下。

select_type

查詢類型

SIMPLE

簡單的 select 查詢,未使用 union 或子查詢

PRIMARY

最外層的 select 查詢

UNION

UNION 中的第二個或隨後的 select 查詢,不依賴於外部查詢的結果集

DEPENDENT UNION

UNION 中的第二個或隨後的 select 查詢,依賴於外部查詢的結果集

UNION RESULT

從UNION的結果集select

SUBQUERY

子查詢中的第一個 select 查詢,不依賴於外部查詢的結果集

DEPENDENT SUBQUERY

子查詢中的第一個 select 查詢,依賴於外部查詢的結果集

DERIVED

用於 from 子句裏有子查詢的狀況, MySQL會遞歸執行這些子查詢, 把結果放在臨時表裏。

UNCACHEABLE SUBQUERY

結果集不能被緩存的子查詢,必須從新爲外 層查詢的每一行進行評估。

UNCACHEABLE UNION

UNION 中的第二個或隨後的 select 查詢,屬於不可緩存的子查詢

table

表名

查詢中的表名

輸出行所引用的表

<derivedX>

匿名子查詢結果集(from子句包含子查詢)

type

鏈接使用的類型,按從最優到最差的類型排序

system

表僅有一行(=系統表)。這是 const 鏈接類型的一個特例。

const

const 用於PRIMARY KEY或UNIQUE索引等值比較時。當查詢的表僅有一行時,使用 System。

eq_ref

用於關聯查詢,從當前表中讀取一行,關聯的字段是當前表的PRIMARY KEY/UNIQUE索引的等值比較。

ref

鏈接不能基於關鍵字選擇單個行,可能查找到多個符合條件的行。ref能夠用於使用=或<=>操做符的帶索引的列。

ref_or_null

如同 ref, 可是 MySQL 必須在初次查找的結果裏找出 null 值的行,而後進行二次查找

index_merge

說明索引合併優化被使用了。key列包含了使用的索引的清單,key_len包含了使用的索引的最長的關鍵元素。

unique_subquery

在某些 IN 查詢中使用此種類型,而不是常規的 ref:value IN (SELECT primary_key FROM single_table WHERE some_expr) 。是一個索引查找函數,能夠徹底替換子查詢,效率更高。

index_subquery

在 某 些 IN 查 詢 中 使 用 此 種 類 型 , 與 unique_subquery 相似,可是查詢的是非惟一性索引: value IN (SELECT key_column FROM single_table WHERE some_expr)

range

只檢索給定範圍的行,使用一個索引來選擇 行。key 列顯示使用了哪一個索引。當使用=、 <>、>、>=、<、<=、IS NULL、<=>、BETWEEN 或者 IN 操做符,用常量比較關鍵字列時,可使用 range。

index

索引全表掃描,只是掃描表的時候按照索引次序進行而不是行。主要優勢就是避免了排序, 可是開銷仍然很是大。

all

對於每一個來自於先前的表的行組合,進行完整的表掃描。

possible_keys

表上已有索引的名稱

指出 MySQL 能在該表中使用哪些索引有助於查詢。若是爲空,說明沒有可用的索引。使用覆蓋索引,則索引只在key列顯示,不在此列顯示

key

表上已有索引的名稱

MySQL 實際從 possible_key 選擇使用的索引。 若是爲 NULL,則沒有使用索引。不多的狀況 下,MYSQL 會選擇優化不足的索引。這種狀況下,能夠在 SELECT 語句中使用 USE INDEX (indexname) force index來強制使用一個索引或者用 IGNORE INDEX(indexname)來強制 MYSQL 忽略索引

key_len

使用索引的長度

使用的索引的長度。在不損失精確性的狀況 下,長度越短越好。組合索引的使用狀況能夠經過索引的長度進行判斷。

ref

 

顯示索引的哪一列被使用了

rows

 

MYSQL 認爲必須檢查的用來返回請求數據的行數

 

extra

Distinct

MySQL發現第1個匹配行後,中止爲當前的行組合搜索更多的行。

Not exists

MySQL可以對查詢進行LEFT JOIN優化,發現1個匹配LEFT JOIN標準的行後,再也不爲前面的的行組合在該表內檢查更多的行。

range checked for each record (index map: #)

MySQL沒有發現好的可使用的索引,但發現若是來自前面的表的列值已知,可能部分索引可使用。對前面的表的每一個行組合,MySQL檢查是否可使用range或index_merge訪問方法來索取行。

Using filesort

表示 MySQL 會對結果使用一個外部索引排序,「文件排序」

Using index

使用覆蓋索引查找數據。

Using temporary

表示 MySQL 在對查詢結果排序時使用臨時表。常見於排序 order by 和分組查詢 group by。

Using where

從存儲引擎獲取告終果集數據,表示MySQL服務器將存儲引擎返回服務層之後再應用WHERE條件過濾。

Using sort_union(...), Using union(...), Using intersect(...)

這些函數說明如何爲index_merge聯接類型合併索引掃描。

Using index for group-by

MySQL發現了一個索引,能夠用來查詢GROUP BY或DISTINCT查詢的全部列,而不要額外搜索硬盤訪問實際的表。而且,按最有效的方式使用索引,以便對於每一個組,只讀取少許索引條目。

 

覆蓋索引的possible_keys和key狀況:

mysql> explain select inventory_id,store_id,film_id from inventory;

+----+-------------+-----------+-------+---------------+----------------------+---------+------+------+-------------+

| id | select_type | table     | type  | possible_keys | key                  | key_len | ref  | rows | Extra       |

+----+-------------+-----------+-------+---------------+----------------------+---------+------+------+-------------+

|  1 | SIMPLE      | inventory | index | NULL          | idx_store_id_film_id | 3       | NULL | 4581 | Using index |

+----+-------------+-----------+-------+---------------+----------------------+---------+------+------+-------------+

1 row in set (0.00 sec)

 

key_len在組合索引中的長度變化

mysql> explain select *  from inventory where store_id=1;

+----+-------------+-----------+------+----------------------+----------------------+---------+-------+------+-------+

| id | select_type | table     | type | possible_keys        | key                  | key_len | ref   | rows | Extra |

+----+-------------+-----------+------+----------------------+----------------------+---------+-------+------+-------+

|  1 | SIMPLE      | inventory | ref  | idx_store_id_film_id | idx_store_id_film_id | 1       | const | 2269 | NULL  |

+----+-------------+-----------+------+----------------------+----------------------+---------+-------+------+-------+

1 row in set (0.01 sec)

 

mysql> explain select *  from inventory where store_id=1 and film_id=1;

+----+-------------+-----------+------+-------------------------------------+----------------------+---------+-------------+------+-------+

| id | select_type | table     | type | possible_keys                       | key                  | key_len | ref         | rows | Extra |

+----+-------------+-----------+------+-------------------------------------+----------------------+---------+-------------+------+-------+

|  1 | SIMPLE      | inventory | ref  | idx_fk_film_id,idx_store_id_film_id | idx_store_id_film_id | 3       | const,const |    4 | NULL  |

+----+-------------+-----------+------+-------------------------------------+----------------------+---------+-------------+------+-------+

1 row in set (0.00 sec)

 

create table t1(id int not null auto_increment,col1 varchar(10),col2 varchar(10),col3 varchar(10), primary key (id), key key_col1_col2_col3(col1,col2,col3));

insert into t1 (col1,col2,col3) values('aa','ab','ac');

insert into t1 (col1,col2,col3) values('ab','aa','ac');

insert into t1 (col1,col2,col3) values('ac','ab','aa');

 

排序和分組字段與索引字段不連續是出現filesort

mysql> explain select col1 from t1 where col1 = 'aa'  order by col3;

+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+------------------------------------------+

| id | select_type | table | type | possible_keys      | key                | key_len | ref   | rows | Extra                                    |

+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+------------------------------------------+

|  1 | SIMPLE      | t1    | ref  | key_col1_col2_col3 | key_col1_col2_col3 | 33      | const |    1 | Using where; Using index; Using filesort |

+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+------------------------------------------+

1 row in set (0.00 sec)

 

mysql> explain select col1 from t1 where col1 = 'aa'  order by col2,col3;

+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+--------------------------+

| id | select_type | table | type | possible_keys      | key                | key_len | ref   | rows | Extra                    |

+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+--------------------------+

|  1 | SIMPLE      | t1    | ref  | key_col1_col2_col3 | key_col1_col2_col3 | 33      | const |    1 | Using where; Using index |

+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+--------------------------+

1 row in set (0.00 sec)

 

mysql> explain select col1 from t1 where col1 in ( 'aa','ab','ac')  group by col2;

+----+-------------+-------+-------+--------------------+--------------------+---------+------+------+-----------------------------------------------------------+

| id | select_type | table | type  | possible_keys      | key                | key_len | ref  | rows | Extra                                                     |

+----+-------------+-------+-------+--------------------+--------------------+---------+------+------+-----------------------------------------------------------+

|  1 | SIMPLE      | t1    | index | key_col1_col2_col3 | key_col1_col2_col3 | 99      | NULL |    3 | Using where; Using index; Using temporary; Using filesort |

+----+-------------+-------+-------+--------------------+--------------------+---------+------+------+-----------------------------------------------------------+

1 row in set (0.00 sec)

 

Using where; Using index同時出現表名索引被用來執行索引鍵值查找(走中間節點找部分索引葉節點)

mysql> explain select col1 from t1 where col1 in ( 'aa','ab','ac')  group by col1,col2;

+----+-------------+-------+-------+--------------------+--------------------+---------+------+------+--------------------------+

| id | select_type | table | type  | possible_keys      | key                | key_len | ref  | rows | Extra                    |

+----+-------------+-------+-------+--------------------+--------------------+---------+------+------+--------------------------+

|  1 | SIMPLE      | t1    | index | key_col1_col2_col3 | key_col1_col2_col3 | 99      | NULL |    3 | Using where; Using index |

+----+-------------+-------+-------+--------------------+--------------------+---------+------+------+--------------------------+

1 row in set (0.00 sec)

 

沒有出現Using where表名索引用來讀取數據(全部索引數據)

mysql> explain select id,col1,col2 from t1;

+----+-------------+-------+-------+---------------+--------------------+---------+------+------+-------------+

| id | select_type | table | type  | possible_keys | key                | key_len | ref  | rows | Extra       |

+----+-------------+-------+-------+---------------+--------------------+---------+------+------+-------------+

|  1 | SIMPLE      | t1    | index | NULL          | key_col1_col2_col3 | 99      | NULL |    3 | Using index |

+----+-------------+-------+-------+---------------+--------------------+---------+------+------+-------------+

1 row in set (0.00 sec)

 

複雜子查詢SQL語句執行過程

mysql> explain select d1.txt, (select idc from tbl_tc) id

    ->   from (select ida id, txt from tbl_ta where txt = 'AAAAA') d1

    -> union (select txt, idb id from tbl_tb);

+----+--------------+------------+-------+---------------+---------+---------+------+------+-----------------+

| id | select_type  | table      | type  | possible_keys | key     | key_len | ref  | rows | Extra           |

+----+--------------+------------+-------+---------------+---------+---------+------+------+-----------------+

|  1 | PRIMARY      | <derived3> | ALL   | NULL          | NULL    | NULL    | NULL |    2 | NULL            |

|  3 | DERIVED      | tbl_ta     | ALL   | NULL          | NULL    | NULL    | NULL |    1 | Using where     |

|  2 | SUBQUERY     | tbl_tc     | index | NULL          | PRIMARY | 4       | NULL |    1 | Using index     |

|  4 | UNION        | tbl_tb     | ALL   | NULL          | NULL    | NULL    | NULL |    1 | NULL            |

| NULL | UNION RESULT | <union1,4> | ALL   | NULL          | NULL    | NULL    | NULL | NULL | Using temporary |

+----+--------------+------------+-------+---------------+---------+---------+------+------+-----------------+

5 rows in set (0.00 sec)

 

a、select txt, idb id from tbl_tb

b、select ida id, txt from tbl_ta where txt = 'AAAAA'

c、select idc from tbl_tc

d、union前最外層的語句

e、合併union結果集

 

order by後的字段與where的字段組合知足最左前綴索引規律

mysql> show index from t1;

+-------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| Table | Non_unique | Key_name           | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |

+-------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| t1    |          0 | PRIMARY            |            1 | id          | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |

| t1    |          1 | key_col1_col2_col3 |            1 | col1        | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |               |

| t1    |          1 | key_col1_col2_col3 |            2 | col2        | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |               |

| t1    |          1 | key_col1_col2_col3 |            3 | col3        | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |               |

+-------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

4 rows in set (0.00 sec)

 

mysql> explain select * from t1 where col1='ac' and col2>'aa' order by col3;

+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+------------------------------------------+

| id | select_type | table | type | possible_keys      | key                | key_len | ref   | rows | Extra                                    |

+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+------------------------------------------+

|  1 | SIMPLE      | t1    | ref  | key_col1_col2_col3 | key_col1_col2_col3 | 33      | const |    1 | Using where; Using index; Using filesort |

+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+------------------------------------------+

1 row in set (0.00 sec)

mysql> alter table t1 add index key_col1_col3 (col1,col3);

mysql> alter table t1 drop index key_col1_col2_col3;

mysql> show index from t1;

+-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| Table | Non_unique | Key_name      | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |

+-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| t1    |          0 | PRIMARY       |            1 | id          | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |

| t1    |          1 | key_col1_col3 |            1 | col1        | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |               |

| t1    |          1 | key_col1_col3 |            2 | col3        | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |               |

+-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

3 rows in set (0.00 sec)

 

mysql> explain select * from t1 where col1='ac' and col2>'aa' order by col3;

+----+-------------+-------+------+---------------+---------------+---------+-------+------+------------------------------------+

| id | select_type | table | type | possible_keys | key           | key_len | ref   | rows | Extra                              |

+----+-------------+-------+------+---------------+---------------+---------+-------+------+------------------------------------+

|  1 | SIMPLE      | t1    | ref  | key_col1_col3 | key_col1_col3 | 33      | const |    1 | Using index condition; Using where |

+----+-------------+-------+------+---------------+---------------+---------+-------+------+------------------------------------+

1 row in set (0.00 sec)

 

LEFT JOIN左鏈接,左邊的行必定都有,因此右邊表是優化關注的重點,右表要儘可能使用索引優化(左表建關聯字段索引一點意義都沒有),右鏈接同樣;

明確指出左右鏈接後,驅動表即已肯定,當經過inner join時,MySQL會選擇帶索引的表做爲被驅動表(後執行)。

CREATE TABLE IF NOT EXISTS classes (

id int(10) unsigned NOT NULL AUTO_INCREMENT,

card int(10) unsigned NOT NULL,

PRIMARY KEY (id)

);

 

CREATE TABLE IF NOT EXISTS book (

bookid int(10) unsigned NOT NULL AUTO_INCREMENT,

card int(10) unsigned NOT NULL,

PRIMARY KEY (bookid)

);

 

mysql> explain select * from classes inner join book on classes.card = book.card;

+----+-------------+---------+------+---------------+------+---------+------+------+----------------------------------------------------+

| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra                                              |

+----+-------------+---------+------+---------------+------+---------+------+------+----------------------------------------------------+

|  1 | SIMPLE      | classes | ALL  | NULL          | NULL | NULL    | NULL |    1 | NULL                                               |

|  1 | SIMPLE      | book    | ALL  | NULL          | NULL | NULL    | NULL |    1 | Using where; Using join buffer (Block Nested Loop) |

+----+-------------+---------+------+---------------+------+---------+------+------+----------------------------------------------------+

2 rows in set (0.00 sec)

 

mysql> alter table classes add index  idx_card (card);

Query OK, 0 rows affected (0.01 sec)

Records: 0  Duplicates: 0  Warnings: 0

 

mysql> explain select * from classes inner join book on classes.card = book.card;

+----+-------------+---------+------+---------------+----------+---------+------------------+------+-------------+

| id | select_type | table   | type | possible_keys | key      | key_len | ref              | rows | Extra       |

+----+-------------+---------+------+---------------+----------+---------+------------------+------+-------------+

|  1 | SIMPLE      | book    | ALL  | NULL          | NULL     | NULL    | NULL             |    1 | NULL        |

|  1 | SIMPLE      | classes | ref  | idx_card      | idx_card | 4       | sakila.book.card |    1 | Using index |

+----+-------------+---------+------+---------------+----------+---------+------------------+------+-------------+

2 rows in set (0.00 sec)

 

mysql> drop index idx_card on classes;

Query OK, 0 rows affected (0.01 sec)

Records: 0  Duplicates: 0  Warnings: 0

 

mysql> alter table book add index  idx_card (card);

Query OK, 0 rows affected (0.01 sec)

Records: 0  Duplicates: 0  Warnings: 0

 

mysql> explain select * from classes inner join book on classes.card = book.card;

+----+-------------+---------+------+---------------+----------+---------+---------------------+------+-------------+

| id | select_type | table   | type | possible_keys | key      | key_len | ref                 | rows | Extra       |

+----+-------------+---------+------+---------------+----------+---------+---------------------+------+-------------+

|  1 | SIMPLE      | classes | ALL  | NULL          | NULL     | NULL    | NULL                |    1 | NULL        |

|  1 | SIMPLE      | book    | ref  | idx_card      | idx_card | 4       | sakila.classes.card |    1 | Using index |

+----+-------------+---------+------+---------------+----------+---------+---------------------+------+-------------+

2 rows in set (0.00 sec)

 

 

用小結果集驅動大結果集,即儘量減小Join語句中NestedLoop的循環次數,同時優化被驅動表的Join索引

JoinBuffer參數的配置

mysql> show variables like '%join%';

+------------------+----------------------+

| Variable_name    | Value                |

+------------------+----------------------+

| join_buffer_size | 262144               |

| max_join_size    | 18446744073709551615 |

+------------------+----------------------+

2 rows in set (0.00 sec)

 

MySQL索引使用注意事項:

一、全索引字段匹配效果最好;

二、最佳左前綴法則;

三、不在索引列上作任何操做(計算、函數、自動或手動類型轉換)會致使索引失效,而轉向全表掃描;

四、索引範圍條件右邊的列沒法使用索引;

五、儘量使用覆蓋索引,避免使用select *語句;

六、條件中使用不等於(!=或<>)時索引失效;

七、is null 或is not null也會使索引失效;

八、like以統配符開頭(%XXX)索引會失效;

九、字符串不加單引號,索引會失效;

十、where子句中使用or鏈接條件會使索引失效;

 

CREATE TABLE t1 (

  id int(11) NOT NULL AUTO_INCREMENT,

  col1 varchar(10) DEFAULT NULL,

  col3 varchar(10) DEFAULT NULL,

  col4 varchar(50) DEFAULT NULL,

  col5 varchar(10) DEFAULT 'a5',

  col2 int(11) DEFAULT '22',

  PRIMARY KEY (id),

  KEY idx_col1234 (col1,col2,col3,col4)

);

 

mysql> explain select * from t1 where col1='aa';

+----+-------------+-------+------+---------------+-------------+---------+-------+------+-----------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref   | rows | Extra                 |

+----+-------------+-------+------+---------------+-------------+---------+-------+------+-----------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 33      | const |    1 | Using index condition |

+----+-------------+-------+------+---------------+-------------+---------+-------+------+-----------------------+

1 row in set (0.00 sec)

 

查詢的列覆蓋索引

mysql> explain select col1 from t1 where col1='aa';

+----+-------------+-------+------+---------------+-------------+---------+-------+------+--------------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref   | rows | Extra                    |

+----+-------------+-------+------+---------------+-------------+---------+-------+------+--------------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 33      | const |    1 | Using where; Using index |

+----+-------------+-------+------+---------------+-------------+---------+-------+------+--------------------------+

1 row in set (0.00 sec)

 

col1,col2使用索引

mysql> explain select *  from t1 where col1='aa' and col2=22;

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+-----------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref         | rows | Extra                 |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+-----------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 38      | const,const |    1 | Using index condition |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+-----------------------+

1 row in set (0.00 sec)

where子句中索引列的順序不影響索引使用狀況(能串聯)

mysql> explain select *  from t1 where col1='aa'  and col2=22 and col3='ab';

+----+-------------+-------+------+---------------+-------------+---------+-------------------+------+-----------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref               | rows | Extra                 |

+----+-------------+-------+------+---------------+-------------+---------+-------------------+------+-----------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 71      | const,const,const |    1 | Using index condition |

+----+-------------+-------+------+---------------+-------------+---------+-------------------+------+-----------------------+

1 row in set (0.00 sec)

mysql> explain select *  from t1 where col1='aa' and col3='ab'  and col2=22;

+----+-------------+-------+------+---------------+-------------+---------+-------------------+------+-----------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref               | rows | Extra                 |

+----+-------------+-------+------+---------------+-------------+---------+-------------------+------+-----------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 71      | const,const,const |    1 | Using index condition |

+----+-------------+-------+------+---------------+-------------+---------+-------------------+------+-----------------------+

1 row in set (0.00 sec)

 

範圍運算對於數值型,則範圍列仍會使用索引,字符型則範圍列不會使用索引

mysql> explain select *  from t1 where col1='aa'  and col2>22 and col3='ab';

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

| id | select_type | table | type  | possible_keys | key         | key_len | ref  | rows | Extra                 |

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

|  1 | SIMPLE      | t1    | range | idx_col1234   | idx_col1234 | 38      | NULL |    1 | Using index condition |

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

1 row in set (0.00 sec)

mysql> explain select col1,col2,col3 from t1 where col1='aa' and col2>'aa' and col3='aa';

+----+-------------+-------+------+---------------------+---------------------+---------+-------+------+--------------------------+

| id | select_type | table | type | possible_keys       | key                 | key_len | ref   | rows | Extra                    |

+----+-------------+-------+------+---------------------+---------------------+---------+-------+------+--------------------------+

|  1 | SIMPLE      | t1    | ref  | indx_col1_col2_col3 | indx_col1_col2_col3 | 33      | const |    1 | Using where; Using index |

+----+-------------+-------+------+---------------------+---------------------+---------+-------+------+--------------------------+

1 row in set (0.00 sec)

注:col1單列的索引長度即爲33

 

mysql> explain select *  from t1 where col1='aa'  and col2=22 and col3='ab' and col4='a4';

+----+-------------+-------+------+---------------+-------------+---------+-------------------------+------+-----------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref                     | rows | Extra                 |

+----+-------------+-------+------+---------------+-------------+---------+-------------------------+------+-----------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 224     | const,const,const,const |    1 | Using index condition |

+----+-------------+-------+------+---------------+-------------+---------+-------------------------+------+-----------------------+

1 row in set (0.00 sec)

索引列順序不影響索引使用

mysql> explain select *  from t1 where col1='aa'  and col2=22 and col4='a4' and col3='ab';

+----+-------------+-------+------+---------------+-------------+---------+-------------------------+------+-----------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref                     | rows | Extra                 |

+----+-------------+-------+------+---------------+-------------+---------+-------------------------+------+-----------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 224     | const,const,const,const |    1 | Using index condition |

+----+-------------+-------+------+---------------+-------------+---------+-------------------------+------+-----------------------+

1 row in set (0.00 sec)

col一、col2使用索引

mysql> explain select *  from t1 where col1='aa'  and col2=22 and col3>'ab' and col4='a4';

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

| id | select_type | table | type  | possible_keys | key         | key_len | ref  | rows | Extra                 |

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

|  1 | SIMPLE      | t1    | range | idx_col1234   | idx_col1234 | 71      | NULL |    1 | Using index condition |

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

1 row in set (0.00 sec)

col一、col二、col三、col4使用索引

mysql> explain select *  from t1 where col1='aa'  and col2=22 and col4>'a4' and col3='ab';

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

| id | select_type | table | type  | possible_keys | key         | key_len | ref  | rows | Extra                 |

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

|  1 | SIMPLE      | t1    | range | idx_col1234   | idx_col1234 | 224     | NULL |    1 | Using index condition |

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

1 row in set (0.00 sec)

 

order by字段與where子句的字段組合能連起來,知足最左前綴法則,col3使用索引排序

mysql> explain select *  from t1 where col1='aa'  and col2=22 and col4='a4' order by  col3;

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref         | rows | Extra                              |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 38      | const,const |    1 | Using index condition; Using where |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

1 row in set (0.00 sec)

mysql> explain select *  from t1 where col1='aa'  and col2=22  order by  col3;

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref         | rows | Extra                              |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 38      | const,const |    1 | Using index condition; Using where |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

1 row in set (0.00 sec)

mysql> explain select *  from t1 where col1='aa'  and col2=22  order by  col4;

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+----------------------------------------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref         | rows | Extra                                              |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+----------------------------------------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 38      | const,const |    1 | Using index condition; Using where; Using filesort |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+----------------------------------------------------+

1 row in set (0.00 sec)

 

order by子句字段與where子句字段組合,且要與索引字段順序一致

mysql> explain select *  from t1 where col1='aa'  and col5='a5'  order by  col2,col3;

+----+-------------+-------+------+---------------+-------------+---------+-------+------+------------------------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref   | rows | Extra                              |

+----+-------------+-------+------+---------------+-------------+---------+-------+------+------------------------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 33      | const |    1 | Using index condition; Using where |

+----+-------------+-------+------+---------------+-------------+---------+-------+------+------------------------------------+

1 row in set (0.00 sec)

mysql> explain select *  from t1 where col1='aa'  and col5='a5'  order by  col3,col2;

+----+-------------+-------+------+---------------+-------------+---------+-------+------+----------------------------------------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref   | rows | Extra                                              |

+----+-------------+-------+------+---------------+-------------+---------+-------+------+----------------------------------------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 33      | const |    1 | Using index condition; Using where; Using filesort |

+----+-------------+-------+------+---------------+-------------+---------+-------+------+----------------------------------------------------+

1 row in set (0.00 sec)

 

where子句包含了col一、col2與order by中的字段能夠組合知足最左前綴法則,同時where加入的字段不影響order by索引的使用

mysql> explain select *  from t1 where col1='aa'  and col2=22  order by  col2,col3;

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref         | rows | Extra                              |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 38      | const,const |    1 | Using index condition; Using where |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

1 row in set (0.00 sec)

mysql> explain select *  from t1 where col1='aa'  and col2=22  order by  col3,col2;

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref         | rows | Extra                              |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 38      | const,const |    1 | Using index condition; Using where |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

1 row in set (0.00 sec)

mysql> explain select *  from t1 where col1='aa'  and col2=22  and col5='a5'  order by  col2,col3;

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref         | rows | Extra                              |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 38      | const,const |    1 | Using index condition; Using where |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

1 row in set (0.00 sec)

mysql> explain select *  from t1 where col1='aa'  and col2=22  and col5='a5'  order by  col3,col2;

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref         | rows | Extra                              |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 38      | const,const |    1 | Using index condition; Using where |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

1 row in set (0.00 sec)

 

group by未使用索引時會增長Using temporary和Using filesort其餘與order by規律一致

mysql> explain select *  from t1 where col1='aa'  and col4='a4'  group  by  col2,col3;

+----+-------------+-------+------+---------------+-------------+---------+-------+------+------------------------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref   | rows | Extra                              |

+----+-------------+-------+------+---------------+-------------+---------+-------+------+------------------------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 33      | const |    1 | Using index condition; Using where |

+----+-------------+-------+------+---------------+-------------+---------+-------+------+------------------------------------+

1 row in set (0.00 sec)

mysql> explain select *  from t1 where col1='aa'  and col4='a4'  group  by  col3,col2;

+----+-------------+-------+------+---------------+-------------+---------+-------+------+---------------------------------------------------------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref   | rows | Extra                                                               |

+----+-------------+-------+------+---------------+-------------+---------+-------+------+---------------------------------------------------------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 33      | const |    1 | Using index condition; Using where; Using temporary; Using filesort |

+----+-------------+-------+------+---------------+-------------+---------+-------+------+---------------------------------------------------------------------+

1 row in set (0.00 sec)

mysql> explain select *  from t1 where col1='aa' and col2=22  and col4='a4'  group  by  col3,col2;

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref         | rows | Extra                              |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 38      | const,const |    1 | Using index condition; Using where |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+------------------------------------+

1 row in set (0.00 sec)

 

like右統配不影響後續索引的使用

mysql> explain select *  from t1 where col1='aa' and col2=22  and col3 like 'a%' and col4='a4';

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

| id | select_type | table | type  | possible_keys | key         | key_len | ref  | rows | Extra                 |

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

|  1 | SIMPLE      | t1    | range | idx_col1234   | idx_col1234 | 224     | NULL |    1 | Using index condition |

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

1 row in set (0.00 sec)

mysql> explain select *  from t1 where col1='aa' and col2=22  and col3 like 'a%';

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

| id | select_type | table | type  | possible_keys | key         | key_len | ref  | rows | Extra                 |

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

|  1 | SIMPLE      | t1    | range | idx_col1234   | idx_col1234 | 71      | NULL |    1 | Using index condition |

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

1 row in set (0.00 sec)

mysql> explain select *  from t1 where col1='aa' and col2=22  and col3 like '%a' and col4='a4';

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+-----------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref         | rows | Extra                 |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+-----------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 38      | const,const |    1 | Using index condition |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+-----------------------+

1 row in set (0.00 sec)

mysql> explain select *  from t1 where col1='aa' and col2=22  and col3 like '%a%' and col4='a4';

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+-----------------------+

| id | select_type | table | type | possible_keys | key         | key_len | ref         | rows | Extra                 |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+-----------------------+

|  1 | SIMPLE      | t1    | ref  | idx_col1234   | idx_col1234 | 38      | const,const |    1 | Using index condition |

+----+-------------+-------+------+---------------+-------------+---------+-------------+------+-----------------------+

1 row in set (0.00 sec)

mysql> explain select *  from t1 where col1='aa' and col2=22  and col3 like 'a%a%' and col4='a4';

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

| id | select_type | table | type  | possible_keys | key         | key_len | ref  | rows | Extra                 |

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

|  1 | SIMPLE      | t1    | range | idx_col1234   | idx_col1234 | 224     | NULL |    1 | Using index condition |

+----+-------------+-------+-------+---------------+-------------+---------+------+------+-----------------------+

1 row in set (0.00 sec)

 

 

 

MySQL刪除列,會自動將該列的組合索引中該列也刪除;

 

rows是核心指標,絕大部分rows小的語句執行必定很快(有例外,下面會講到)。因此優化語句基本上都是在優化rows。

 

建索引的幾大原則

1.最左前綴匹配原則,很是重要的原則,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就中止匹配,好比a = 1 and b = 2 and c > 3 and d = 4 若是創建(a,b,c,d)順序的索引,d是用不到索引的,若是創建(a,b,d,c)的索引則均可以用到,a,b,d的順序能夠任意調整。

2.=和in能夠亂序,好比a = 1 and b = 2 and c = 3 創建(a,b,c)索引能夠任意順序,mysql的查詢優化器會幫你優化成索引能夠識別的形式

3.儘可能選擇區分度高的列做爲索引,區分度的公式是count(distinct col)/count(*),表示字段不重複的比例,比例越大咱們掃描的記錄數越少,惟一鍵的區分度是1,而一些狀態、性別字段可能在大數據面前區分度就是0,那可能有人會問,這個比例有什麼經驗值嗎?使用場景不一樣,這個值也很難肯定,通常須要join的字段咱們都要求是0.1以上,即平均1條掃描10條記錄

4.索引列不能參與計算,保持列「乾淨」,好比from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,緣由很簡單,b+樹中存的都是數據表中的字段值,但進行檢索時,須要把全部元素都應用函數才能比較,顯然成本太大。因此語句應該寫成create_time = unix_timestamp(’2014-05-29’);

5.儘可能的擴展索引,不要新建索引。好比表中已經有a的索引,如今要加(a,b)的索引,那麼只須要修改原來的索引便可

rows是核心指標,絕大部分rows小的語句執行必定很快(有例外,下面會講到)。因此優化語句基本上都是在優化rows。

 

參考資料:

http://database.51cto.com/art/201108/285341.htm

相關文章
相關標籤/搜索