1. 程式人生 > >MySQL 通過多個示例學習索引

MySQL 通過多個示例學習索引

cde 註意 實例 query affect 大於等於 篩選條件 notice highlight

  最近在準備面試,關於索引這一塊,發現很多以前忽略的點,這裏好好整理一下

  

首先為什麽要建立索引

  一本書,有章、節、段、行這種單位。

  如果現在需要找一個內容:第9章>第2節>第3段>第4行>第5個字。

  如果沒有索引(目錄),那麽,就必須從第一頁開始,按照這個順序:第1章>第1節>第1段>第1行>第1個字開始,順序查找,也就是說,如果運氣足夠壞,那麽,找到目標的時候,已經將整本書都差不多掃了一遍。

  但是現在,如果建立了索引(目錄),只是建立了 “章” 的索引:每一章的第一頁,那麽,我們開始查找的時候,並不是從第1章開始,我們可以根據目錄,查找到第9章的頁數,然後直接翻到第9章的那章內容,初始就是第9章>第1節>第1段>第1行>第1個字,然後仍舊開始順序查找,那麽這個時候,雖然仍然有點慢,但是已經快了很多很多。

  現在,如果建立(章-節)的索引,記錄每一章的每一個小節的第1頁,那麽我們開始查找的時候,可以通過讀一下索引,直接找到第9章的第2小節,然後從這1小節的第1段的第1行的第1個字開始查找。仍舊順序查找。

  很好,你會想,可以建立(章-節-段)的索引,那麽,一開始就可以直接定位到第9章>第2小節>第3段,然後從這段的第1行的第1個字開始順序查找。

  那麽,有沒有必要建立(章-節-段-行)的索引呢?可以根據情況而定。

索引類型

  有很多中索引,比如:

  1、普通索引:最基本的索引,沒有任何約束限制

  2、唯一索引:與主鍵索引類似,但是不允許出現相同的值(唯一性約束)。

  3、主鍵索引:特殊的唯一索引,不允許有空值。

  4、復蓋索引(組合索引):將多個列組合在一起創建索引,可以覆蓋多個列,比如“章-節-段”建立索引

  5、外鍵索引:只有Innodb支持,保證數據一致性、完整性,實現級聯操作。

  6、全文索引:只有MyISAM引擎支持,並且只支持對英文進行全文檢索。

建立索引

  假設有一個user表(用戶表)

mysql> desc user;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| uid   | int(11)  | NO   | PRI | NULL    | auto_increment |
| uname | char(20) | NO   | UNI | NULL    |                |
| addr  | char(20) | NO   | MUL | NULL    |                |
| token | char(20) | NO   |     | NULL    |                |
+-------+----------+------+-----+---------+----------------+

  uid因為是主鍵,所以已經默認創建了主鍵索引  

  為uname字段建立一個唯一索引,為addr字段建立普通索引:

  token字段不建立索引

mysql> create unique index uname_index on user(uname);
mysql> create index addr_index on user(addr);

  

查看索引

mysql> show index from user;
*************************** 1. row ***************************
        Table: user
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: uid
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
*************************** 2. row ***************************
        Table: user
   Non_unique: 0
     Key_name: uname_index
 Seq_in_index: 1
  Column_name: uname
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
*************************** 3. row ***************************
        Table: user
   Non_unique: 1
     Key_name: addr_index
 Seq_in_index: 1
  Column_name: addr
    Collation: A
  Cardinality: NULL
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
3 rows in set (0.00 sec)

  

插入數據

  使用pdo循環插入10000條記錄,各個字段除了uid自增之外,都是隨機值。

<?php
    $pdo = new PDO("mysql:host=127.0.0.1;dbname=MyDb;charset=utf8", "root", "root");

    $stmt = $pdo->prepare("insert into user (uname, addr, token) values (?, ?, ?)");

    $str = "abcdefghijklmnopqrstuvwxzy";

    for ($j = 0; $j < 10000; $j++) {
        $name = "";
        $addr = "";
        $token = "";
        for ($i = 0; $i < 7; $i++) {
            $name .= $str[mt_rand(0, 25)];
            $addr .= $str[mt_rand(0, 25)];
            $token .= $str[mt_rand(0, 25)];
        }
        $stmt->execute(array($name, $addr, $token));
    }

?>

  

是否會使用索引?

  示例1:

mysql> explain select count(*) from user;
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                        |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Select tables optimized away |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
1 row in set (0.00 sec)

  未使用索引,因為沒有使用where子句,索引是在查找的時候(有where的時候才使用索引)。

  示例2:

mysql> explain select * from user where uname=‘outalwa‘;
+----+-------------+-------+-------+---------------+-------------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys | key         | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+---------------+-------------+---------+-------+------+-------+
|  1 | SIMPLE      | user  | const | uname_index   | uname_index | 60      | const |    1 |       |
+----+-------------+-------+-------+---------------+-------------+---------+-------+------+-------+
1 row in set (0.00 sec)

mysql> explain select * from user where uname!=‘outalwa‘;
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | user  | ALL  | uname_index   | NULL | NULL    | NULL | 10000 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.00 sec)

mysql> explain select * from user where uname<>‘outalwa‘;
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | user  | ALL  | uname_index   | NULL | NULL    | NULL | 10000 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.00 sec)

  對於一個建了索引的列來說,如果使用=、!=、<>來判斷字段值是否與一個值相等的時候,只有使用=的時候會使用索引,而!=和<>不會使用索引。

  示例3:

mysql> explain select * from user where uid=‘9999‘ and uname=‘muqehaq‘;                              
+----+-------------+-------+-------+---------------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys       | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+---------------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | user  | const | PRIMARY,uname_index | PRIMARY | 4       | const |    1 |       |
+----+-------------+-------+-------+---------------------+---------+---------+-------+------+-------+
1 row in set (0.06 sec)                                                                              

  因為uid建立了主鍵索引,uname建立了唯一索引,使用and表示(並且)的關系時,會使用各自的索引。只掃描了1行數據就找到了

  

  示例4:

mysql> explain select * from user where uid=‘9999‘ or uname=‘muqehaq‘;
+----+-------------+-------+-------------+---------------------+---------------------+---------+------+------+-----------------------------------------------+
| id | select_type | table | type        | possible_keys       | key                 | key_len | ref  | rows | Extra                                         |
+----+-------------+-------+-------------+---------------------+---------------------+---------+------+------+-----------------------------------------------+
|  1 | SIMPLE      | user  | index_merge | PRIMARY,uname_index | PRIMARY,uname_index | 4,60    | NULL |    2 | Using union(PRIMARY,uname_index); Using where |
+----+-------------+-------+-------------+---------------------+---------------------+---------+------+------+-----------------------------------------------+
1 row in set (0.00 sec)

  因為uid建立了主鍵索引,uname建立了唯一索引,使用or表示(或)的關系時,使用了索引。

  示例5

mysql> explain select * from user where uid=‘9999‘ and token=‘dakghzz‘;
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | user  | const | PRIMARY       | PRIMARY | 4       | const |    1 |       |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+

  uid有主鍵索引,token沒有建立索引,使用and來連接條件,可以使用索引。

  如果條件是token=‘dakghzz‘ and uid=9999 ,同樣會使用索引。

  示例6

mysql> explain select * from user where uid=‘9999‘ or token=‘dakghzz‘;
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | user  | ALL  | PRIMARY       | NULL | NULL    | NULL | 10000 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.00 sec)

  uid有主鍵索引,但是token沒有建立索引,使用or來連接的時候,可以看到,查詢並沒有使用索引。

  示例7

mysql> explain select count(*) from user where uid < 1000;
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
|  1 | SIMPLE      | user  | range | PRIMARY       | PRIMARY | 4       | NULL | 1401 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

mysql> explain select count(*) from user where uid between 10 and 1000;
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
|  1 | SIMPLE      | user  | range | PRIMARY       | PRIMARY | 4       | NULL | 1388 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

mysql> explain select count(*) from user where uid >10 and uid < 1000;
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
|  1 | SIMPLE      | user  | range | PRIMARY       | PRIMARY | 4       | NULL | 1386 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

  可以看到,對一個創建了索引的列,使用 大於、小於、大於等於、小於等於、between and 最為篩選條件,都會使用索引。

  示例8

mysql> explain select * from user where uname=null;
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                                               |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Impossible WHERE noticed after reading const tables |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
1 row in set (0.00 sec)

mysql> explain select * from user where uname!=null;
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                                               |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Impossible WHERE noticed after reading const tables |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
1 row in set (0.00 sec)

mysql> explain select * from user where uname is null;
+----+-------------+-------+------+---------------+------+---------+------+------+------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra            |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Impossible WHERE |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------+
1 row in set (0.00 sec)

mysql> explain select * from user where uname is not null;
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | user  | ALL  | uname_index   | NULL | NULL    | NULL | 10000 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.00 sec)

    對於一個建立了索引的列來說,判斷字段是否為0時,使用=,!=,is null這幾種方式都不會使用索引,但是is not null可以使用索引。

  示例9

mysql> explain select * from user where uname like ‘%wolwgrc‘;
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | user  | ALL  | NULL          | NULL | NULL    | NULL | 10000 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.00 sec)

mysql> explain select * from user where uname like ‘%wolwgrc%‘;
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | user  | ALL  | NULL          | NULL | NULL    | NULL | 10000 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+

mysql> explain select * from user where uname like ‘wolwgrc‘;
+----+-------------+-------+-------+---------------+-------------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key         | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+-------------+---------+------+------+-------------+
|  1 | SIMPLE      | user  | range | uname_index   | uname_index | 60      | NULL |    1 | Using where |
+----+-------------+-------+-------+---------------+-------------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> explain select * from user where uname like ‘wolwgrc%‘;
+----+-------------+-------+-------+---------------+-------------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key         | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+-------------+---------+------+------+-------------+
|  1 | SIMPLE      | user  | range | uname_index   | uname_index | 60      | NULL |    1 | Using where |
+----+-------------+-------+-------+---------------+-------------+---------+------+------+-------------+
1 row in set (0.00 sec)

  對一個已經建立了索引的列使用模式匹配的時候,%keyword、%keyword%不會使用索引,而keyword和keyword%會使用索引。

普通索引的註意事項

  1、 對於一個沒有where的查詢,不會使用索引,所以,在創建索引的時候,應該以where子句的字段為準,而不是select後面的字段為準。

  2、對於一個建了索引的列來說,如果使用=、!=、<>來判斷字段值是否與一個值相等的時候,只有使用=的時候會使用索引,而!=和<>不會使用索引。

  3、where包含多個字段,如果每個字段都建了索引,那麽使用and和or連接的時候,查詢會使用索引。

  4、where包含多個字段,如果一部分字段建立了索引,而有一部分字段沒有建立索引,那麽使用and連接的時候,查詢的時候,建立了索引的字段會使用索引,而沒有建立索引的字段不會使用索引。

  5、where包含多個字段,如果一部分字段建立了索引,而有一部分字段沒有建立索引,那麽使用or連接的時候,查詢的時候,不會使用索引。

  6、對一個創建了索引的列,使用 大於、小於、大於等於、小於等於、between and 最為篩選條件,都會使用索引。

  7、對於一個建立了索引的列來說,判斷字段是否為0時,使用=,!=,is null這幾種方式都不會使用索引,但是is not null可以使用索引。

  8、對一個已經建立了索引的列使用模式匹配的時候,%keyword、%keyword%不會使用索引,而keyword和keyword%會使用索引。

復合索引

  復合索引有前綴原則,後面示例會解釋。

  刪除之前為uname字段和addr字段創建的索引。

  創建一個復合索引,包含uname、addr、token,命令如下:

mysql> drop index uname_index on user;                                                                                                                               
Query OK, 10000 rows affected (0.27 sec)                                                                                                                             
Records: 10000  Duplicates: 0  Warnings: 0                                                                                                                           
                                                                                                                                                                     
mysql> drop index addr_index on user;                                                                                                                                
Query OK, 10000 rows affected (0.24 sec)                                                                                                                             
Records: 10000  Duplicates: 0  Warnings: 0                                                                                                                           
                                                                                                                                                                     
mysql> create index three_fields_index on user(uname, addr, token);                                                                                                  
Query OK, 10000 rows affected (0.25 sec)                                                                                                                             
Records: 10000  Duplicates: 0  Warnings: 0                                                                                                                           
                                                                                                                                                                     
mysql> show index from user;                                                                                                                                         
+-------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| Table | Non_unique | Key_name           | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
+-------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| user  |          0 | PRIMARY            |            1 | uid         | A         |       10000 |     NULL | NULL   |      | BTREE      |         |               | 
| user  |          1 | three_fields_index |            1 | uname       | A         |       10000 |     NULL | NULL   |      | BTREE      |         |               | 
| user  |          1 | three_fields_index |            2 | addr        | A         |       10000 |     NULL | NULL   |      | BTREE      |         |               | 
| user  |          1 | three_fields_index |            3 | token       | A         |       10000 |     NULL | NULL   |      | BTREE      |         |               | 
+-------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 

  可以從上面索引查詢結果中看出,uname、addr、token都包含在一個索引中(Key_name相同)。

覆蓋索引的使用示例

  下面的實例,簡化一下,創建的索引是key(uname, addr, token),那麽對應key(A, B, C)

  示例1

mysql> explain select * from user where uname=‘muqehaq‘ and addr=‘hgommlp‘ and token=‘dakghzz‘;
+----+-------------+-------+------+--------------------+--------------------+---------+-------------------+------+-------------+
| id | select_type | table | type | possible_keys      | key                | key_len | ref               | rows | Extra       |
+----+-------------+-------+------+--------------------+--------------------+---------+-------------------+------+-------------+
|  1 | SIMPLE      | user  | ref  | three_fields_index | three_fields_index | 180     | const,const,const |    1 | Using where |
+----+-------------+-------+------+--------------------+--------------------+---------+-------------------+------+-------------+
1 row in set (0.00 sec)

mysql> explain select * from user where addr=‘hgommlp‘ and token=‘dakghzz‘ and uname=‘muqehaq‘;
+----+-------------+-------+------+--------------------+--------------------+---------+-------------------+------+-------------+
| id | select_type | table | type | possible_keys      | key                | key_len | ref               | rows | Extra       |
+----+-------------+-------+------+--------------------+--------------------+---------+-------------------+------+-------------+
|  1 | SIMPLE      | user  | ref  | three_fields_index | three_fields_index | 180     | const,const,const |    1 | Using where |
+----+-------------+-------+------+--------------------+--------------------+---------+-------------------+------+-------------+
1 row in set (0.00 sec)

  因為建立了uname-addr-token的聯合索引,在where中,三個字段都出現了(和建立索引時使用的字段列相同時),此時,和每個字段的順序無關,都會使用索引。

  結論:where A=‘xx‘ and B=‘xx‘ and 或者where C=‘xx‘ and B=‘xx‘ and A=‘xx‘會使用索引。

  示例2

mysql> explain select * from user where uname=‘muqehaq‘ and addr=‘hgommlp‘;
+----+-------------+-------+------+--------------------+--------------------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys      | key                | key_len | ref         | rows | Extra       |
+----+-------------+-------+------+--------------------+--------------------+---------+-------------+------+-------------+
|  1 | SIMPLE      | user  | ref  | three_fields_index | three_fields_index | 120     | const,const |    1 | Using where |
+----+-------------+-------+------+--------------------+--------------------+---------+-------------+------+-------------+
1 row in set (0.00 sec)

  示例:where A=‘xx‘ and B=‘xx‘

  結論:會使用索引,使用復合索引中的前兩個字段的索引。

  示例3:

mysql> explain select * from user where uname=‘muqehaq‘ and token=‘dakghzz‘;
+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys      | key                | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+-------------+
|  1 | SIMPLE      | user  | ref  | three_fields_index | three_fields_index | 60      | const |    1 | Using where |
+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+-------------+
1 row in set (0.00 sec)

mysql> explain select * from user where token=‘dakghzz‘ and uname=‘muqehaq‘;
+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys      | key                | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+-------------+
|  1 | SIMPLE      | user  | ref  | three_fields_index | three_fields_index | 60      | const |    1 | Using where |
+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+-------------+
1 row in set (0.00 sec)

  示例:where A=‘xxx‘ and C=‘xx‘ 或者 where C=‘xx‘ and A=‘xxx‘

  結論:查詢A字段的時候,會使用復合索引中的A那一部分,但是查詢C字段的時候,並不會使用復合索引。

  原因:因為沒有使用復合索引中的B字段。

  示例4

mysql> explain select * from user where addr=‘hgommlp‘ and token=‘dakghzz‘;
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | user  | ALL  | NULL          | NULL | NULL    | NULL | 10000 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.00 sec)

  示例:where B=‘xxx‘ and C=‘xxx‘

  結論:不會使用索引。

  原因:沒有使用復合索引中B前面的A字段索引。

  示例5

mysql> explain select * from user where uname=‘muqehaq‘;                                                              
+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+-------------+  
| id | select_type | table | type | possible_keys      | key                | key_len | ref   | rows | Extra       |  
+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+-------------+  
|  1 | SIMPLE      | user  | ref  | three_fields_index | three_fields_index | 60      | const |    1 | Using where |  
+----+-------------+-------+------+--------------------+--------------------+---------+-------+------+-------------+  
1 row in set (0.00 sec)                                                                                               
                                                                                                 
mysql> explain select * from user where addr=‘hgommlp‘;                                                               
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+                     
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |                     
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+                     
|  1 | SIMPLE      | user  | ALL  | NULL          | NULL | NULL    | NULL | 10000 | Using where |                     
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+                     
1 row in set (0.00 sec)                                                                                               
                                                                                                                      
mysql> explain select * from user where token=‘dakghzz‘;                                                              
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+                     
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |                     
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+                     
|  1 | SIMPLE      | user  | ALL  | NULL          | NULL | NULL    | NULL | 10000 | Using where |                     
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+                     

  示例:where A=‘xxx‘ 結論:會使用索引。

  示例:where B=‘xxx‘ 結論:不會使用索引。

  示例:where C=‘xxx‘ 結論:不會使用索引。

復合索引的使用總結

  假設創建了key(a,b,c)復合索引,那麽:

  where a = 1 and b = 2 and c = 3; 會使用索引

  where a = 1 and c = 3 and b = 2; 會使用索引

  where a = 1 and b = 2 ; 會使用索引

  where a = 1;會使用索引

  where a = 1 and c = 3; 不會使用索引,因為c前面的b沒有使用

  where b = 2 and c = 3; 不會使用索引,因為b前面的a沒有使用

MySQL 通過多個示例學習索引