mysql索引
mysql索引
准备
- 数据库与表
| 1 | CREATE DATABASE demo; | 
关于索引
原理
可以把索引理解为一本书的目录,可以通过目录迅速找到自己想要的章节,本质上就是为了提高查询速度。
分析
通常使用explain来分析一条sql语句中索引使用情况。后期会有章节专门介绍explain命令的使用方法。
- 用法: - EXPLAIN SQL- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- mysql> explain select * from t_users where id=1890 \G; 
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: t_users
 partitions: NULL
 type: const
 possible_keys: PRIMARY
 key: PRIMARY
 key_len: 8
 ref: const
 rows: 1
 filtered: 100.00
 Extra: NULL
 1 row in set, 1 warning (0.00 sec)
索引创建原则
- 对于重复度比较高的字段不适合做索引,比如性别,充其量就是男,女,其他,做索引作用不大。
- 创建合适的唯一索引
- 遵循最左匹配原则
- 对于经常用于排序(order by),分组(group by)的字段,我们可以建立索引
- 索引所在的列不能参与计算,不然会失效
- 尽量扩展索引,不要新增加索引。
普通索引(简单索引)
最常见的索引之一,没有任何我约束。
| 1 | CREATE INDEX index_name ON table_name(column); | 
测试:
| 1 | explain select * from t_test where a='123' \G; | 
联合索引(符合索引)
将多个字段用于创建索引。联合索引最重要的就是最左原则,他决定索引是否生效。
| 1 | CREATE INDEX index_name ON table_name(column1,column2,column3...); | 
索引最左原则
| 1 | CREATE INDEX index_name ON table_name(column1, column2); | 
比如表t_test拥有字段x,a,b,c,d,y, 现在将字段a,b,c,d创建为联合索引,实际上是建立了a,a,b,a,b,c,a,b,c,d四个索引。
| 1 | CREATE INDEX index_a_b_c_d ON t_test(a,b,c,d); | 
- 对于联合索引,mysql会依照创建索引时的字段顺序向右匹配,直到遇到范围查询(>,<,between,like)就停止匹配。 - 1 - SELECT * FROM t_test WHERE a=1 AND b=2 AND c>3 AND d=6; - 此时 - c无法使用索引。
- 对于查询中的 - =和- in,只要- WHERE里面对于索引字段的是- a,- a,b,- a,b,c,- a,b,c,d四种情况之一,那么字段条件后的字段顺序是不要求的, mysql会按照你创建索引字段顺序去比对。- 1 
 2- SELECT * FROM t_test WHERE a=1 AND b=2 AND c=3 AND d=6; 
 SELECT * FROM t_test WHERE c=3 AND d=6 AND a=1 AND b=2;
有几个疑问
对于上面(a,b,c,d)组成的联合索引
- A:以下索引会生效吗? - 1 - SELECT a,b,c,d,x FROM t_test WHERE b=1 AND x=5; - 答案是不会生效 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- mysql> EXPLAIN SELECT a,b,c,d,x FROM t_test WHERE b=1 \G; 
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: t_test
 partitions: NULL
 type: ALL
 possible_keys: NULL
 key: NULL
 key_len: NULL
 ref: NULL
 rows: 1
 filtered: 100.00
 Extra: Using where
 1 row in set, 1 warning (0.00 sec)
- B:以下索引会生效吗? - 1 - SELECT a,b,c,d FROM t_test WHERE b=1 AND x=5; - 答案是会生效 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18- mysql> EXPLAIN SELECT a,b,c,d FROM t_test WHERE b=1 \G; 
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: t_test
 partitions: NULL
 type: index
 possible_keys: NULL
 key: index_a_b_c_d
 key_len: 313
 ref: NULL
 rows: 1
 filtered: 100.00
 Extra: Using where; Using index
 1 row in set, 1 warning (0.00 sec)
 
 ERROR:
 No query specified
- B生效的原因在于查询条件中只有包含索引的字段,查询内容也全部在索引字段中,所以它只需要操作索引表即可。 - A不生效是因为除了操作索引表之外,还需要从数据表中拿到额外的字段数据。 
唯一索引
| 1 | CREATE UNIQUE INDEX index_name ON table_name(column); | 
主键索引
| 1 | CREATE TABLE `table_name` ( | 
全文索引
| 1 | CREATE FULLTEXT INDEX index_name ON table_name(column) | 
注意事项
- 使用索引的时候尽量不要使用like, 在语句 - like value%时索引会生效,但是- like %value%不会生效- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31- mysql> explain select * from t_test where a like "a%" \G; 
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: t_test
 partitions: NULL
 type: range
 possible_keys: index_a_b_c_d
 key: index_a_b_c_d
 key_len: 153
 ref: NULL
 rows: 1
 filtered: 100.00
 Extra: Using index condition
 1 row in set, 1 warning (0.00 sec)
 mysql> explain select * from t_test where a like "%a%"\G;
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: t_test
 partitions: NULL
 type: ALL
 possible_keys: NULL
 key: NULL
 key_len: NULL
 ref: NULL
 rows: 1
 filtered: 100.00
 Extra: Using where
 1 row in set, 1 warning (0.00 sec)
- 在索引列运算会导致索引失效 
- 如果where后面的条件字段数据类型与匹配值的类型不一致,可能会导致索引失效 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31- mysql> explain select * from t_test where a="1"\G; 
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: t_test
 partitions: NULL
 type: ref
 possible_keys: index_a_b_c_d
 key: index_a_b_c_d
 key_len: 153
 ref: const
 rows: 1
 filtered: 100.00
 Extra: NULL
 1 row in set, 1 warning (0.00 sec)
 mysql> explain select * from t_test where a=1 \G;
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: t_test
 partitions: NULL
 type: ALL
 possible_keys: index_a_b_c_d
 key: NULL
 key_len: NULL
 ref: NULL
 rows: 1
 filtered: 100.00
 Extra: Using where
 1 row in set, 3 warnings (0.00 sec)
- 索引所在列的值不能为null。只有该列包含null值,则该索引列会失效。