MySQL索引

1.若是索引了多列,遵照最左前綴法則。所謂最左前綴,指的是查詢從索引的最左前列開始,而且不跳過索引中的列。mysql

mysql> explain select uid, fuid, name from ptb where uid=1378109017;sql

+----+-------------+-------+------+---------------+----------+---------+-------+------+-------+函數

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

+----+-------------+-------+------+---------------+----------+---------+-------+------+-------+ui

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 4       | const |   33 |       |unix

+----+-------------+-------+------+---------------+----------+---------+-------+------+-------+排序

1 row in set (0.00 sec)索引

 

mysql> explain select uid, fuid, name from ptb where uid=1378109018 and fuid=1378109017;開發

+----+-------------+-------+------+---------------+----------+---------+-------------+------+-------+rem

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

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

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 8       | const,const |    1 |       |

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

1 row in set (0.00 sec)

 

 

因爲….沒有使用索引. 使用索引失敗,致使MySQL採用ALL訪問策略,即全表查詢.在開發中,應該儘可能避免全表查詢。

mysql> explain select uid, fuid, name from ptb where fuid=1378109017;

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

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

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

|  1 | SIMPLE      | ptb   | ALL  | NULL          | NULL | NULL    | NULL | 15373 | Using where |

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

1 row in set (0.02 sec)

 

mysql> explain select uid, fuid, name from ptb where fuid=1378109017 and uid=1378109018;

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

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

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

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 8       | const,const |    1 |       |

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

1 row in set (0.00 sec)

 

 

2.當MySQL估計檢查的行數可能會「太多」,範圍查找優化將不會被採用。

mysql> explain select uid, fuid, name from ptb where uid>1478109017;

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

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

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

|  1 | SIMPLE      | ptb   | range | uid_fuid      | uid_fuid | 4       | NULL |    1 | Using where |

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

1 row in set (0.00 sec)

 

mysql> explain select uid, fuid, name from ptb where uid>1278109017;

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

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

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

|  1 | SIMPLE      | ptb   | ALL  | uid_fuid      | NULL | NULL    | NULL | 15373 | Using where |

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

1 row in set (0.00 sec)

第2條語句使用了全表查詢,它與第1條語句惟一的區別在於須要檢查的行數遠遠多於第1條語句。在應用中,可能不會碰到這麼大的查詢,可是應該避免這樣的查詢出現: select uid from users where registered < 1295001384

 

3.索引列不該該做爲表達式的一部分,即不能在索引列上使用函數。

mysql> explain select uid, fuid, name from ptb where uid=1478109017;

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

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

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

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 4       | const |    1 |       |

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

1 row in set (0.02 sec)

 

mysql> explain select uid, fuid, name from ptb where abs(uid)=1478109017;

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

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

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

|  1 | SIMPLE      | ptb   | ALL  | NULL          | NULL | NULL    | NULL | 15373 | Using where |

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

1 row in set (0.02 sec)

 

mysql> explain select uid, fuid, name from ptb where uid * 1 =1478109017;

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

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

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

|  1 | SIMPLE      | ptb   | ALL  | NULL          | NULL | NULL    | NULL | 15373 | Using where |

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

1 row in set (0.00 sec)

第2和3條語句都有使用表達式,索引派不上用場。

 

4.儘可能借用覆蓋索引,減小select * from …語句的用法.

mysql> explain select uid, fuid from ptb where uid=1378109017;

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

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

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

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 4       | const |   33 | Using index |

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

1 row in set (0.00 sec)

 

mysql> explain select uid, fuid, id from ptb where uid=1378109017;

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

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

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

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 4       | const |   33 | Using index |

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

1 row in set (0.00 sec)

 

mysql> explain select fuid,uid, id from ptb where uid=1378109017;

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

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

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

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 4       | const |   33 | Using index |

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

1 row in set (0.00 sec)

 

mysql> explain select uid, fuid, name from ptb where uid=1378109017;

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

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

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

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 4       | const |   33 |       |

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

1 row in set (0.00 sec)

第1句Extra中使用了Using index表示使用了覆蓋索引。第2句和第3句也使用了覆蓋索引,雖然ID不在索引uid_fuid索引列中,可是InnoDB二次索引(second index)葉子頁的值就是PK值,不一樣於MyISAM。Extra部分的Using index表示應用了索引,不要跟type中的index混淆。第4句沒有使用覆蓋索引,由於name不在索引中。

 

 

???????????????????????????????????????????????????

mysql> explain select fuid,uid, id from ptb where fuid=1378109017;

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

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

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

|  1 | SIMPLE      | ptb   | index | NULL          | uid_fuid | 8       | NULL | 15373 | Using where; Using index |

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

1 row in set (0.00 sec)

 

 

5.ORDER BY子句,儘可能使用Index方式排序,避免使用FileSort方式排序
           MySQL支持二種方式的排序,FileSort和Index,後者效率高,它指MySQL掃描索引自己完成排序。FileSort方式效率較低。ORDER BY知足如下狀況,會使用Index方式排序:
      a)  ORDER BY 語句使用索引最左前列。以下:

mysql> explain select uid from ptb order by uid;

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

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

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

|  1 | SIMPLE      | ptb   | index | NULL          | uid_fuid | 8       | NULL | 15373 | Using index |

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

1 row in set (0.00 sec)

     b)  使用Where子句與Order BY子句條件列組合知足索引最左前列。以下:

mysql> explain select uid from ptb where uid=1378109017 order by fuid;

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

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

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

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 4       | const |   33 | Using where; Using index |

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

1 row in set (0.64 sec)


如下狀況,會使用FileSort方式的查詢:

     a)  檢查的行數過多,且沒有使用覆蓋索引。以下句雖然跟前一句(explain select uid from ptb order by uid)同樣,order by使用了索引最左前列uid,但依然使用了filesort方式排序,由於name並不在索引中,因此沒辦法只掃描索引。

mysql> explain select uid, name from ptb order by uid;

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

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

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

|  1 | SIMPLE      | ptb   | ALL  | NULL          | NULL | NULL    | NULL | 15373 | Using filesort |

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

1 row in set (0.00 sec)


     b)  使用了不一樣的索引,MySQL每次只採用一個索引。以下句中,order by出現二個索引,分別是uid_fuid和彙集索引(pk)

mysql> explain select uid from ptb order by uid, id;

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

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

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

|  1 | SIMPLE      | ptb   | index | NULL          | uid_fuid | 8       | NULL | 15373 | Using index; Using filesort |

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

1 row in set (0.00 sec)


      c)  對索引列同時使用了ASC和DESC,經過where語句將order by中索引列轉爲常量,則除外。以下第1句和第2句在order by子句中,都出現了ASC和DESC排序。可是第1句卻使用了filesort方式排序,是由於第2句where uid取出排序須要的數據,MySQL將其轉爲常量,它的ref列爲const。

mysql> explain select uid from ptb order by uid ASC, fuid DESC;

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

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

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

|  1 | SIMPLE      | ptb   | index | NULL          | uid_fuid | 8       | NULL | 15373 | Using index; Using filesort |

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

1 row in set (0.00 sec)

 

mysql> explain select uid, name from ptb where uid=1478109017 order by uid ASC, fuid DESC;

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

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

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

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 4       | const |    1 | Using where |

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

1 row in set (0.00 sec)


     d)   where語句與order by語句,使用了不一樣的索引。

mysql> explain select uid, fuid from ptb where uid=1278 order by name;

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

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

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

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 4       | const |    1 | Using where; Using filesort |

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

1 row in set (0.01 sec)

 

 

mysql> explain select uid,name from ptb where uid=1278 order by id;

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

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

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

|  1 | SIMPLE      | ptb   | index | uid_fuid      | PRIMARY | 4       | NULL | 15373 | Using where |

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

1 row in set (0.00 sec)

 

mysql> explain select uid, name from ptb where uid=1278 order by id;    ?????

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

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

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

|  1 | SIMPLE      | ptb   | index | uid_fuid      | PRIMARY | 4       | NULL | 15373 | Using where |

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

1 row in set (0.00 sec)

 

mysql> explain select uid from ptb where uid=1278 order by id;    ?????

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

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

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

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 4       | const |    1 | Using where; Using index; Using filesort |

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

1 row in set (0.00 sec)

 

mysql> explain select id,uid, name from ptb where uid=1278 order by id;  ???????

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

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

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

|  1 | SIMPLE      | ptb   | index | uid_fuid      | PRIMARY | 4       | NULL | 15373 | Using where |

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

1 row in set (0.00 sec)

 

mysql> explain select id,uid from ptb where uid=1278 order by id;  ????

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

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

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

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 4       | const |    1 | Using where; Using index; Using filesort |

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

1 row in set (0.00 sec)

 

mysql> explain select id,name from ptb where uid=1278 order by id;             ???????

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

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

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

|  1 | SIMPLE      | ptb   | index | uid_fuid      | PRIMARY | 4       | NULL | 15373 | Using where |

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

1 row in set (0.00 sec)


      e)  where語句或者ORDER BY語句中索引列使用了表達式,包括函數表達式。

mysql> explain select uid, name from ptb where uid*1=1478109017 order by uid;

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

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

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

|  1 | SIMPLE      | ptb   | ALL  | NULL          | NULL | NULL    | NULL | 15373 | Using where; Using filesort |

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

1 row in set (0.02 sec)

 

mysql> explain select uid, name from ptb where uid=1378 order by abs(uid);

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

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

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

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 4       | const |    1 | Using where; Using filesort |

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

1 row in set (0.00 sec)

 

      f)  where 語句與ORDER BY語句組合知足最左前綴,但where語句中使用了條件查詢。雖然where與order by構成了索引最左有綴的條件,可是where子句中使用的是條件查詢。以下:

mysql> explain select uid, name from ptb where uid>1478109017 order by fuid;

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

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

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

|  1 | SIMPLE      | ptb   | range | uid_fuid      | uid_fuid | 4       | NULL |    1 | Using where; Using filesort |

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

1 row in set (0.00 sec)


      g)  order by子句中加入了非索引列,且非索引列不在where子句中。

mysql> explain select uid, name from ptb where uid>1478109017 order by name;

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

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

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

|  1 | SIMPLE      | ptb   | range | uid_fuid      | uid_fuid | 4       | NULL |    1 | Using where; Using filesort |

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

1 row in set (0.00 sec)

 

      h)  order by或者它與where組合沒有知足索引最左前列。以下where與order by組合,不知足索引最左前列. (uid, name)跳過了fuid

mysql> explain select uid, name from ptb where uid=1478109017 order by name;

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

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

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

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 4       | const |    1 | Using where; Using filesort |

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

1 row in set (0.00 sec)

 

mysql> explain select uid from ptb where fuid=1478109017 order by uid, name;

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

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

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

|  1 | SIMPLE      | ptb   | ref  | uid_fuid      | uid_fuid | 4       | const |    1 | Using where; Using filesort |

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

1 row in set (0.00 sec)

 

mysql> explain select uid from ptb order by uid, name;

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

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

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

|  1 | SIMPLE      | ptb   | ALL  | NULL          | NULL | NULL    | NULL | 15373 | Using filesort |

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

1 row in set (0.00 sec)


      i)  當使用left join,使用右邊的表字段排序。以下儘管user.uid是pk,依然會使用filesort排序。

create table puse(

 uid int unsigned not null,

 puid int unsigned not null default 0,

 access tinyint unsigned not null default 0,

 primary key(uid)

)

 

insert into puse(uid) values('1378109017'),('1378108952'),('1378108951');

 

mysql> explain select p.uid, p.name from ptb as p left join puse as u on p.uid=u.uid where p.uid=1378109017 order by u.uid;

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

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

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

|  1 | SIMPLE      | p     | ref   | uid_fuid      | uid_fuid | 4       | const |   33 | Using temporary; Using filesort |

|  1 | SIMPLE      | u     | const | PRIMARY       | PRIMARY  | 4       | const |    1 | Using index                     |

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

2 rows in set (0.00 sec)

 

6.慎用left join語句,避免建立臨時表

使用left join語句的時候,避免出現建立臨時表。儘可能不要用left join,採用分而治之。非要使用時,要詢問本身是否是真要必須使用。

mysql> explain select p.uid, p.name from ptb as p left join puse as u on p.uid=u.uid where p.uid=1378109017 order by p.uid, p.fuid,u.access;

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

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

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

|  1 | SIMPLE      | p     | ref   | uid_fuid      | uid_fuid | 4       | const |   33 | Using temporary; Using filesort |

|  1 | SIMPLE      | u     | const | PRIMARY       | PRIMARY  | 4       | const |    1 |                                 |

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

2 rows in set (0.00 sec)

 

7.高選擇性索引列

儘可能使用高選擇性的索引來過濾數據。高選擇性指Cardinality/#T 越接近1,選擇性越高,其中Cardinality指表中索引列不重複值(行)的總數。PK和惟一索引,具備最高的選擇性,即1。推薦可選性達到20%以上。

mysql> select id from ptb where uid = 1378109017;

+------+

| id   |

+------+

| 2926 |

..

| 3215 |

| 3225 |

..

| 3268 |

+------+

33 rows in set (0.00 sec)

 

mysql> explain select id, uid, fuid from ptb where uid=1378109017 and id = 3225;

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

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

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

|  1 | SIMPLE      | ptb   | const | PRIMARY,uid_fuid | PRIMARY | 4       | const |    1 |       |

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

1 row in set (0.00 sec)

這裏有二個索引可供使用,而MySQL選擇PRIMARY,是由於它具備更高的選擇性。

8.謹防where子句中的ORwhere語句使用or,且沒有使用覆蓋索引,會進行全表掃描。應該儘可能避免這樣OR語句。儘可能使用UNION代替OR

mysql> explain select uid, fuid  from ptb where uid = 1578109017 or fuid=1478109017;

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

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

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

|  1 | SIMPLE      | ptb   | index | uid_fuid      | uid_fuid | 8       | NULL | 15373 | Using where; Using index |

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

1 row in set (0.00 sec)

 

mysql> explain select uid, name  from ptb where uid = 1578109017 or fuid=1478109017;

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

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

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

|  1 | SIMPLE      | ptb   | ALL  | uid_fuid      | NULL | NULL    | NULL | 15373 | Using where |

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

1 row in set (0.00 sec)

 

       第1句雖然使用了索引,可是查行時間依然不能夠恭維,mysql要檢查的行不少,可是返回的行卻不多.Extra中的using where表示須要經過where子句扔棄不須要的數據行。

9.LIMIT與覆蓋索引 limit子句,使用覆蓋索引時比沒有使用覆蓋索引會快不少

 

 

create table ptb(

 id int unsigned not null auto_increment,

 uid int unsigned not null default 0,

 fuid int unsigned not null default 0,

 name varchar(50) not null default '',

 age  tinyint not null default 0,

 fsex tinyint not null default 0,

 primary key(id)

) engine=InnoDB AUTO_INCREMENT=1;

alter table ptb add index uid_fuid(uid, fuid);

 

delimiter //

drop procedure if exists proc_ptb //

create procedure proc_ptb()

begin

   declare counter int default 0;

   declare age int default 20;

   declare tfuid int default 0;

   while(counter < 5000) do

     if(age > 30) then

       select unix_timestamp() into tfuid;

       set age=20;  

     end if;

     set age=age+1;

     set tfuid=tfuid+1;

     set counter=counter+1;

     insert into ptb(uid, fuid, age) values( tfuid, tfuid, age);

   end while;

end

//

delimiter ;

相關文章
相關標籤/搜索