最近在准备面试,关于索引这一块,发现很多以前忽略的点,这里好好整理一下

  

首先为什么要建立索引

  一本书,有章、节、段、行这种单位。

  如果现在需要找一个内容:第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 | MUL | NULL | |
| addr | char(20) | NO | | NULL | |
| token | char(20) | NO | | NULL | |
+-------+----------+------+-----+---------+----------------+
5 rows in set (0.05 sec)

  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:

  

插入数据

  使用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)

  如果存储引擎是innodb的话,对于主键索引列,使用 大于、小于、大于等于、小于等于、between and 作为筛选条件,都会使用索引。

  如果存储引擎是MyISAM的话,即使是索引列,使用是大于、小于、大于等于、小于等于、between and作为筛选条件,都不会使用索引。

  无论是哪种存储引擎,即使某一列创建了索引,如果使用大于、小于、大于等于、小于等于、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、如果存储引擎是innodb的话,对于主键索引列,使用 大于、小于、大于等于、小于等于、between and 作为筛选条件,都会使用索引。

  7、如果存储引擎是MyISAM的话,即使是索引列,使用 大于、小于、大于等于、小于等于、between and作为筛选条件,都不会使用索引。

  8、无论是哪种存储引擎,即使某一列创建了索引,如果使用大于、小于、大于等于、小于等于、between and作为筛选条件,都不会使用索引。

  9、对于一个建立了索引的列来说,判断字段是否为0时,使用=,!=,is null,is not nulll这几种方式都不会使用索引。

  10、对一个已经建立了索引的列使用模式匹配的时候,%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) mysql> explain select * from user where addr='hgommlp' 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 | 120 | const,const | 1 | Using where |
+----+-------------+-------+------+--------------------+--------------------+---------+-------------+------+-------------+
1 row in set (0.00 sec)

  示例:where A='xx' and B='xx' 或者 where B='xx' and A='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 b = 2 and a = 1;      注意,这也是会使用复合索引的ab

  where a = 1;会使用索引

  where a = 1 and c = 3;   不会使用索引,因为c前面的b没有使用

  where b = 2 and c = 3;   不会使用索引,因为b前面的a没有使用

MySQL 通过多个示例学习索引的更多相关文章

  1. MySQL学习----索引的使用

    一.什么是索引?为什么要建立索引? 索引用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的 ...

  2. 10 | MySQL为什么有时候会选错索引? 学习记录

    <MySQL实战45讲>10 | MySQL为什么有时候会选错索引? 学习记录http://naotu.baidu.com/file/e7c521276650e80fe24584bc9a6 ...

  3. Mysql学习---索引的学习 180101

    索引:约束 + 快速查找 索引是数据库中用于帮助用户快速查询数据的一种数据结构.类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,然后直接获取即可. 问:为什么索引可以这么快?[类似 ...

  4. 数据库表设计时一对一关系存在的必要性 数据库一对一、一对多、多对多设计 面试逻辑题3.31 sql server 查询某个表被哪些存储过程调用 DataTable根据字段去重 .Net Core Cors中间件解析 分析MySQL中哪些情况下数据库索引会失效

    数据库表设计时一对一关系存在的必要性 2017年07月24日 10:01:07 阅读数:694 在表设计过程中,我无意中觉得一对一关系觉得好没道理,直接放到一张表中不就可以了吗?真是说,网上信息什么都 ...

  5. mysql笔记02 创建高性能的索引

    创建高性能的索引 1. 索引(在MySQL中也叫做"键(key)")是存储引擎用于快速找到记录的一种数据结构. 2. 索引可以包含一个或多个列的值.如果索引包含多个列,那么列的顺序 ...

  6. mysql的limit性能,数据库索引问题,dblog问题

    mysql的limit性能,数据库索引问题,dblog问题,redis学习 继续学习. dblog实际上是把日志记录在另一个数据库里面. 问题1: 一张表定义了5个索引,但是sql语句中用到了3个有索 ...

  7. MySQL优化GROUP BY-松散索引扫描与紧凑索引扫描

    满足GROUP BY子句的最一般的方法是扫描整个表并创建一个新的临时表,表中每个组的所有行应为连续的,然后使用该临时表来找到组并应用累积函数(如果有).在某些情况中,MySQL能够做得更好,即通过索引 ...

  8. NumPy学习(索引和切片,合并,分割,copy与deep copy)

    NumPy学习(索引和切片,合并,分割,copy与deep copy) 目录 索引和切片 合并 分割 copy与deep copy 索引和切片 通过索引和切片可以访问以及修改数组元素的值 一维数组 程 ...

  9. MYsql 锁详解 锁 与索引的关系

    原文:http://blog.csdn.net/xifeijian/article/details/20313977#t10   mysql innodb的锁是通过锁索引来实现的.   select ...

随机推荐

  1. python根据关键字以及id值爬取图虫网上高质量大图

    import requests import re import os import time print("ready....") def downPic(dirs, keywo ...

  2. IE6浏览器无法打开QQ邮箱

    原因:未启用TLS1.0 解决方法: 打开IE浏览器,依次打开 [Internet]→[高级],在 设置 选项卡中,勾选[使用TLS1.0],然后点击[确定]保存修改,重启浏览器即可.

  3. Apache中httpd.conf文件的详解

    PHP中,Apache的配置至关重要,特别是httpd.conf这个文件,它是Apache中的核心文件.好了,废话不说,今天将这个文件中的一些内容讲解一番. ServerRoot "d:/w ...

  4. if else; while; break;continue ----流程控制系列

    第一种语法: if 条件: # @引号是为了把条件和结果分开. 结果1 # 一个Tab或者4个空格 @告诉程序满足上面的if条件才会执行结果1结果2 #如果条件为真(True),执行结果1,然后执行结 ...

  5. 推酷文章中编写js组件系列文章整理

    一步一步实现JS拖拽插件 http://www.tuicool.com/articles/RBbmMjY JS组件系列——基于Bootstrap Ace模板的菜单和Tab页效果分享 http://ww ...

  6. 【Teradata】grouping和rollup窗口函数

    1.group by后带rollup子句 先按一定的规则产生多种分组,然后返回各个分组所产生的结果集的并集,且没有去掉重复数据(统计出的数据是求和还是最大值还是平均值等这就取决于SELECT后的聚合函 ...

  7. 给 datepicker 设定日期格式

    datepicker 是 JQueryUI 提供的日期控件,仅提供日期选择,不提供时间,但基本够用了. 其日期格式默认是:mm/dd/yy 格式字符代表的含义如下: d - 每月的第几天 (没有前导零 ...

  8. Java面试知识点之设计模式(一)

    前言:关于设计模式,在框架中用的比较多.在平常接触最为频繁的估计是单例模式了,因此笔者在此对设计模式相关知识点进行总结. 1.设计模式的种类 总体来说,设计模式分为3大类总共23种: 1)创建型模式, ...

  9. tomcat 改端口 运维最最重要的就是有看日志的习惯

    tomcat一台机器上多实例更改端口需要改三个端口 改tomcat关闭端口 <Server port="9006" shutdown="SHUTDOWN" ...

  10. Java常见的几种内存溢出及解决方案

    1.JVM Heap(堆)溢出:java.lang.OutOfMemoryError: Java heap space JVM在启动的时候会自动设置JVM Heap的值, 可以利用JVM提供的-Xmn ...