索引优化
1 | CREATE TABLE `staffs` ( |
索引失效的原因
1.全值匹配我最爱
1 | mysql> EXPLAIN SELECT * from staffs WHERE `name` = 'July'; |
2.最佳左前缀法则
最左列建立的索引不能丢,中间的索引不能断。(带头大哥不能死,中间兄弟不能断)
如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17mysql> EXPLAIN SELECT * from staffs WHERE age = 23 AND pos = 'dev';
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | staffs | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
mysql> EXPLAIN SELECT * from staffs WHERE `name` = 'July' AND pos = 'dev';
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------+------+----------+-----------------------+
| 1 | SIMPLE | staffs | NULL | ref | idx_staffs_nameAgePos | idx_staffs_nameAgePos | 74 | const | 1 | 33.33 | Using index condition |
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)
mysql>
3.不在索引列上做任何操作(计算,函数,自动or手动类型转换),会导致索引失效而转向全表扫描。
1 | mysql> SELECT * from staffs WHERE LEFT(`name`,4) = 'July'; |
4.存储引擎不能使用索引中范围条件右边的列 (age > 25)
1 | mysql> EXPLAIN SELECT * from staffs WHERE `name` = 'July' AND age > 23 AND pos = 'dev'; |
5.尽量使用覆盖索引(只访问索引的查询:索引列和查询列一致),减少select * 的操作。
1 | mysql> EXPLAIN SELECT name,age,pos from staffs WHERE `name` = 'July' AND age = 23 AND pos = 'dev'; |
额外多了Using index,性能会更好。
6.mysql在使用不等于(!= 或者 <> )的时候无法使用索引会导致全表扫描。
1 | mysql> EXPLAIN SELECT name,age,pos from staffs WHERE `name` = 'July'; |
7.is null, is not null 也无法使用索引。
1 | mysql> EXPLAIN SELECT name,age,pos from staffs WHERE `name` is null; |
8.like以通配符开头(‘%abc…’),mysql索引失效会变成全表扫描的操作。
1 | CREATE TABLE `tbl_user` ( |
before index
1 | mysql> EXPLAIN SELECT uname,age FROM tbl_user WHERE uname LIKE '%aa%'; |
创建索引
1 | CREATE INDEX idx_user_unameAge ON tbl_user (uname,age); |
1 | mysql> EXPLAIN SELECT id FROM tbl_user WHERE uname LIKE '%aa%'; |
解决like ‘%字符串%’,时索引失效的问题。采用覆盖索引的方式。(只查询有索引字段的列)
9.字符串不加单引号索引失效。
1 | mysql> SELECT * FROM staffs WHERE `name` = 5000; |
10.少用or,用它来连接是会索引失效。
1 | mysql> EXPLAIN SELECT * FROM staffs WHERE `name` = 'July' OR `name`= 'z3'; |
小结
1 | 假设index(a,b,c) |