• 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,用它连接时索引会失效

    没有修不好的电脑
  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    详解以太坊世界状态
    VDF 不是工作量证明
    以太坊:Go-Ethereum: 编译运行
    【转】理解分布式账本技术: 经济学视角
    Counterfactual 项目:广义的以太坊状态通道
    Solidity 安全:已知攻击方法和常见防御模式综合列表
    Verge 攻击解析
    以太坊区块链的轻客户端
  • 原文地址:https://www.cnblogs.com/duniqb/p/12702483.html
Copyright © 2020-2023  润新知