MySQL -- 10 -- MySQL联合索引最左匹配原则

原文链接:MySQL – 10 – MySQL联合索引最左匹配原则


相关文章:


一、联合索引

  • 联合索引又称复合索引,是指由多个字段组成的索引

二、最左匹配原则

  • 最左匹配原则,MySQL 会一直向右匹配,如果遇到范围查询 (>、<、between、like) 就会停止匹配,如:a = 1 and b = 2 and c > 3 and d = 4,如果建立 (a, b, c, d) 顺序的联合索引,那么 d 就使用不了联合索引了;如果建立 (a, b, d, c) 顺序的联合索引,则都可以用的到,a、b、d 的顺序可以任意调整

  • = 和 in 可以乱序,比如:a = 1 and b = 2 and c = 3,如果建立 (a, b, c) 顺序的联合索引,则可以任意顺序,MySQL 的查询优化器会帮我们将其优化成索引可识别的形式


二、最左匹配原则成因

  • MySQL 创建联合索引的规则,是首先对联合索引最左边 (第一个) 的索引字段的数据进行排序,然后在第一个字段数据排序的基础上,再对第二个索引字段的数据进行排序,以此类推,相当于实现了类似 order by field1 filed2 ... filedN 这样的排序规则

  • 因此在没有使用第一个字段的情况下,直接使用第二个或后面的字段进行条件判断是无法使用索引的,这就是 MySQL 为什么强调联合索引最左匹配原则的原因


三、举例说明

  • 创建学生表

    DROP TABLE IF EXISTS tbl_student_left;
    CREATE TABLE tbl_student_left (
      id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
      uuid VARCHAR(40) NOT NULL COMMENT '学生唯一标识',
      name VARCHAR(20) NOT NULL COMMENT '学生姓名',
      age INT(3) UNSIGNED NOT NULL COMMENT '学生年龄',
      sex TINYINT(1) UNSIGNED NOT NULL COMMENT '学生性别: 1=男,0=女',
      PRIMARY KEY (id),
      KEY idx_uuid_name_age (uuid, name, age)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='学生信息表';
    
    • 如上所示,我们建立了 (uuid, name, age) 顺序的联合索引 idx_uuid_name_age_sex,按照最左匹配原则,实际相当于是建立了 (uuid)(uuid, name)(uuid, age)(uuid, name, age) 四个索引

    • 其他类似于 (name)(age)(name, age) 等组合则使用不了联合索引

    • 这里我们插入 1000 条数据来作为分析说明

  • 使用联合索引示例

    • 示例一 (uuid)

      mysql> explain select * from tbl_student_left where uuid = '426fcfd1-c8de-11ea-84aa-00163e0d9873';
      +----+-------------+------------------+------------+------+-------------------+-------------------+---------+-------+------+----------+-------+
      | id | select_type | table            | partitions | type | possible_keys     | key               | key_len | ref   | rows | filtered | Extra |
      +----+-------------+------------------+------------+------+-------------------+-------------------+---------+-------+------+----------+-------+
      |  1 | SIMPLE      | tbl_student_left | NULL       | ref  | idx_uuid_name_age | idx_uuid_name_age | 122     | const |    1 |   100.00 | NULL  |
      +----+-------------+------------------+------------+------+-------------------+-------------------+---------+-------+------+----------+-------+
      1 row in set, 1 warning (0.00 sec)
      
    • 示例二 (uuid, name)

      mysql> explain select * from tbl_student_left where uuid = '426fcfd1-c8de-11ea-84aa-00163e0d9873' and name = 'NrDHrYmKurDVyRvMc';
      +----+-------------+------------------+------------+------+-------------------+-------------------+---------+-------------+------+----------+-------+
      | id | select_type | table            | partitions | type | possible_keys     | key               | key_len | ref         | rows | filtered | Extra |
      +----+-------------+------------------+------------+------+-------------------+-------------------+---------+-------------+------+----------+-------+
      |  1 | SIMPLE      | tbl_student_left | NULL       | ref  | idx_uuid_name_age | idx_uuid_name_age | 184     | const,const |    1 |   100.00 | NULL  |
      +----+-------------+------------------+------------+------+-------------------+-------------------+---------+-------------+------+----------+-------+
      1 row in set, 1 warning (0.00 sec)
      
    • 示例三 (uuid, age)

      mysql> explain select * from tbl_student_left where uuid = '426fcfd1-c8de-11ea-84aa-00163e0d9873' and age = 22;
      +----+-------------+------------------+------------+------+-------------------+-------------------+---------+-------+------+----------+-----------------------+
      | id | select_type | table            | partitions | type | possible_keys     | key               | key_len | ref   | rows | filtered | Extra                 |
      +----+-------------+------------------+------------+------+-------------------+-------------------+---------+-------+------+----------+-----------------------+
      |  1 | SIMPLE      | tbl_student_left | NULL       | ref  | idx_uuid_name_age | idx_uuid_name_age | 122     | const |    1 |    10.00 | Using index condition |
      +----+-------------+------------------+------------+------+-------------------+-------------------+---------+-------+------+----------+-----------------------+
      1 row in set, 1 warning (0.00 sec)
      
    • 示例四 (uuid, name, age)

      mysql> explain select * from tbl_student_left where uuid = '426fcfd1-c8de-11ea-84aa-00163e0d9873' and name = 'NrDHrYmKurDVyRvMc' and age = 22;
      +----+-------------+------------------+------------+------+-------------------+-------------------+---------+-------------------+------+----------+-------+
      | id | select_type | table            | partitions | type | possible_keys     | key               | key_len | ref               | rows | filtered | Extra |
      +----+-------------+------------------+------------+------+-------------------+-------------------+---------+-------------------+------+----------+-------+
      |  1 | SIMPLE      | tbl_student_left | NULL       | ref  | idx_uuid_name_age | idx_uuid_name_age | 188     | const,const,const |    1 |   100.00 | NULL  |
      +----+-------------+------------------+------------+------+-------------------+-------------------+---------+-------------------+------+----------+-------+
      1 row in set, 1 warning (0.00 sec)
      
  • 无法使用联合索引示例

    • 示例一 (name)

      mysql> explain select * from tbl_student_left where name = 'NrDHrYmKurDVyRvMc';
      +----+-------------+------------------+------------+------+---------------+------+---------+------+------+----------+-------------+
      | id | select_type | table            | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
      +----+-------------+------------------+------------+------+---------------+------+---------+------+------+----------+-------------+
      |  1 | SIMPLE      | tbl_student_left | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 1000 |    10.00 | Using where |
      +----+-------------+------------------+------------+------+---------------+------+---------+------+------+----------+-------------+
      1 row in set, 1 warning (0.00 sec)
      
    • 示例二 (age)

      mysql> explain select * from tbl_student_left where age = 22;
      +----+-------------+------------------+------------+------+---------------+------+---------+------+------+----------+-------------+
      | id | select_type | table            | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
      +----+-------------+------------------+------------+------+---------------+------+---------+------+------+----------+-------------+
      |  1 | SIMPLE      | tbl_student_left | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 1000 |    10.00 | Using where |
      +----+-------------+------------------+------------+------+---------------+------+---------+------+------+----------+-------------+
      1 row in set, 1 warning (0.00 sec)
      
    • 示例三 (name, age)

      mysql> explain select * from tbl_student_left where name = 'NrDHrYmKurDVyRvMc' and age = 22;
      +----+-------------+------------------+------------+------+---------------+------+---------+------+------+----------+-------------+
      | id | select_type | table            | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
      +----+-------------+------------------+------------+------+---------------+------+---------+------+------+----------+-------------+
      |  1 | SIMPLE      | tbl_student_left | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 1000 |     1.00 | Using where |
      +----+-------------+------------------+------------+------+---------------+------+---------+------+------+----------+-------------+
      1 row in set, 1 warning (0.01 sec)
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值