mysql 前缀索引失效_MySQL索引失效的10大原因

基本表信息:

mysql> desc staffs;

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

| Field | Type | Null | Key | Default | Extra |

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

| id | int(11) | NO | PRI | NULL | auto_increment |

| name | varchar(24) | NO | | | |

| age | int(11) | NO | | 0 | |

| pos | varchar(20) | NO | | | |

| add_time | timestamp | NO | | CURRENT_TIMESTAMP | |

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

5 rows in set (0.00 sec)

mysql> select * from staffs;

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

| id | name | age | pos | add_time |

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

| 1 | z3 | 22 | manager | 2019-03-10 19:52:42 |

| 2 | July | 22 | dev | 2019-03-10 19:52:42 |

| 3 | 2000 | 22 | dev | 2019-03-10 19:52:42 |

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

3 rows in set (0.00 sec)

mysql> show index from staffs;

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

| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |

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

| staffs | 0 | PRIMARY | 1 | id | A | 2 | NULL | NULL | | BTREE | | |

| staffs | 1 | idx_staffs_nameAgePos | 1 | name | A | 3 | NULL | NULL | | BTREE | | |

| staffs | 1 | idx_staffs_nameAgePos | 2 | age | A | 3 | NULL | NULL | | BTREE | | |

| staffs | 1 | idx_staffs_nameAgePos | 3 | pos | A | 3 | NULL | NULL | | BTREE | | |

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

4 rows in set (0.00 sec)

1.全值匹配我最爱

2.最佳左前缀法则

如果索引了多列,要遵守此规则,指的是从索引最左前列开始并且不跳过索引中的列

带头大哥不能死,中间兄弟不能断

mysql> mysql> 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.01 sec)

3.不在索引列上做任何操作

计算、函数、(自动或手动)类型转换,会导致索引失效而转向全表扫描

mysql> explain select * from staffs where name= 'July';

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

| 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 | 100.00 | NULL |

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

1 row in set, 1 warning (0.00 sec)

mysql> explain select * from staffs where left(name,4)= 'July';

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

| 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 | 100.00 | Using where |

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

1 row in set, 1 warning (0.00 sec)

4.存储引擎不能使用索引中范围条件右边的列

范围之后全失效

mysql> explain select * from staffs where name='July' and age =22;

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

| 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 | 78 | const,const | 1 | 100.00 | NULL |

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

1 row in set, 1 warning (0.00 sec)

mysql> explain select * from staffs where name='July' and age =22 and pos='manager';

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

| 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 | 140 | const,const,const | 1 | 100.00 | NULL |

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

1 row in set, 1 warning (0.00 sec)

5.尽量使用覆盖索引(只访问索引的查询(索引列和查询列一直)),减少select *

mysql> explain select * from staffs where name='July' and age=25 and pos='manager';

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

| 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 | 140 | const,const,const | 1 | 100.00 | NULL |

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

1 row in set, 1 warning (0.00 sec)

mysql> explain select name, age, pos from staffs where name='July' and age=25 and pos='manager';

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

| 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 | 140 | const,const,const | 1 | 100.00 | Using index |

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

1 row in set, 1 warning (0.00 sec)

6.mysql在使用不等于(!=或<>)时候,无法使用索引导致全表扫描

mysql> explain select * from staffs where name='July';

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

| 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 | 100.00 | NULL |

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

1 row in set, 1 warning (0.00 sec)

mysql> explain select * from staffs where name!='July';

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

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

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

| 1 | SIMPLE | staffs | NULL | ALL | idx_staffs_nameAgePos | NULL | NULL | NULL | 3 | 66.67 | Using where |

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

1 row in set, 1 warning (0.00 sec)

mysql> explain select * from staffs where name <> 'July';

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

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

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

| 1 | SIMPLE | staffs | NULL | ALL | idx_staffs_nameAgePos | NULL | NULL | NULL | 3 | 66.67 | Using where |

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

1 row in set, 1 warning (0.00 sec)

7.is null,is not null也无法使用索引

mysql> explain select * from staffs where name is null;

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

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

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

| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE |

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

1 row in set, 1 warning (0.00 sec)

mysql> explain select * from staffs where name is not null;

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

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

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

| 1 | SIMPLE | staffs | NULL | ALL | idx_staffs_nameAgePos | NULL | NULL | NULL | 3 | 66.67 | Using where |

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

1 row in set, 1 warning (0.00 sec)

8.like以通配符开头,mysql索引失效会编程全表扫描的操作

百分like加右边

mysql> explain select * from staffs where name like '%July%';

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

| 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 like '%July';

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

| 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 like 'July%';

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

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

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

| 1 | SIMPLE | staffs | NULL | range | idx_staffs_nameAgePos | idx_staffs_nameAgePos | 74 | NULL | 1 | 100.00 | Using index condition |

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

1 row in set, 1 warning (0.00 sec)

9.字符串不加单引号,索引失效

避免隐式类型转换

10.少用or,用它连接时索引会失效

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值