当前位置: 首页 > news >正文

mysql索引最左前缀法则、使用场景

提示:mysql索引最左前缀使用的规则,以及索引失效和部分字段索引失效

文章目录

  • 索引使用法则
    • 最左前缀法则
  • 索引执行explain分析
    • 遵守联合索引最左前缀法则(索引有效)
    • 未遵守联合索引最左前缀法则(索引失效或部分索引失效)
  • 思考


索引使用法则

最左前缀法则

联合索引(多列索引)要遵守最左前缀法则(最左边的字段必须存在,跳过某一字段后面字段索引失效)造成索引失效或者部分索引失效
1、创建表

city  | CREATE TABLE `city` (`ID` int NOT NULL AUTO_INCREMENT,`Name` char(35) NOT NULL DEFAULT '',`CountryCode` char(3) NOT NULL DEFAULT '',`District` char(20) NOT NULL DEFAULT '',`Info` json DEFAULT NULL,PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=4080 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci 

2、创建联合索引(多列索引)

mysql> create index idx_Name_CountryCode_District on city (Name,CountryCode,District);Query OK, 0 rows affected (0.16 sec)
Records: 0  Duplicates: 0  Warnings: 0

create index idx_字段1_字段2......字段n

3、查看索引
show index city;

| Table | Non_unique | Key_name                      | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+-------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| city  |          0 | PRIMARY                       |            1 | ID          | A         |        4079 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| city  |          1 | idx_Name_CountryCode_District |            1 | Name        | A         |        3998 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| city  |          1 | idx_Name_CountryCode_District |            2 | CountryCode | A         |        4056 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| city  |          1 | idx_Name_CountryCode_District |            3 | District    | A         |        4078 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
+-------+------------+-------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+

Name,CountryCode,District三个字段创建的联合索引正常显示!

上述步骤创建联合索引以及查看联合索引等工作完成,

索引执行explain分析

遵守联合索引最左前缀法则(索引有效)

1、全表执行计划查询

mysql> explain select * from city;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | city  | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 4079 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

type:全表扫描
key:未使用到索引

2、第一个索引字段Name执行查询:

mysql> explain select * from city where Name='Jabaliya'-> ;
+----+-------------+-------+------------+------+-------------------------------+-------------------------------+---------+-------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys                 | key                           | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+-------+------------+------+-------------------------------+-------------------------------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | city  | NULL       | ref  | idx_Name_CountryCode_District | idx_Name_CountryCode_District | 140     | const |    1 |   100.00 | Using index condition |
+----+-------------+-------+------------+------+-------------------------------+-------------------------------+---------+-------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

key:使用的所以有Name_CountryCode_District
key_len;索引长度=140也是Name索引长度=140

3、前两个字段Name、CountryCode索引查询执行

mysql> explain select * from city where Name='Jabaliya'and CountryCode='VIR';
+----+-------------+-------+------------+------+-------------------------------+-------------------------------+---------+-------------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys                 | key                           | key_len | ref         | rows | filtered | Extra                 |
+----+-------------+-------+------------+------+-------------------------------+-------------------------------+---------+-------------+------+----------+-----------------------+
|  1 | SIMPLE      | city  | NULL       | ref  | idx_Name_CountryCode_District | idx_Name_CountryCode_District | 152     | const,const |    1 |   100.00 | Using index condition |
+----+-------------+-------+------------+------+-------------------------------+-------------------------------+---------+-------------+------+----------+-----------------------+

key_len:152,上述Name索引字段为140,CountryCode字段索引长度等于152-140=12

4、三个字段Name、CountryCode、District索引查询执行

mysql> explain select * from city where Name='Jabaliya'and CountryCode='VIR' and District='Manicaland';
+----+-------------+-------+------------+------+-------------------------------+-------------------------------+---------+-------------------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys                 | key                           | key_len | ref               | rows | filtered | Extra                 |
+----+-------------+-------+------------+------+-------------------------------+-------------------------------+---------+-------------------+------+----------+-----------------------+
|  1 | SIMPLE      | city  | NULL       | ref  | idx_Name_CountryCode_District | idx_Name_CountryCode_District | 232     | const,const,const |    1 |   100.00 | Using index condition |
+----+-------------+-------+------------+------+-------------------------------+-------------------------------+---------+-------------------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

key_len:District索引长度等于=232-152

上述三种索引查询情况下索引都正常履行了自身的职责,遵守了联合索引(多列索引)的最做前缀法则,所有索引都正常,未造成索引失效

未遵守联合索引最左前缀法则(索引失效或部分索引失效)

1.第一个索引字段、第三个索引字段联合查询执行:

mysql> explain select * from city where Name='Jabaliya'and  District='Manicaland';
+----+-------------+-------+------------+------+-------------------------------+-------------------------------+---------+-------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys                 | key                           | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+-------+------------+------+-------------------------------+-------------------------------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | city  | NULL       | ref  | idx_Name_CountryCode_District | idx_Name_CountryCode_District | 140     | const |    1 |    10.00 | Using index condition |
+----+-------------+-------+------------+------+-------------------------------+-------------------------------+---------+-------+------+----------+-----------------------+

当执行第一个字段索引和第三个字段索引时,跳过第二个字段索引进行查询的时,key_len显示为140,和使用explain select * from city where Name='Jabaliya’查询的索引长度一样,name的索引字段等于140,而District索引长度未0,表示District字段索引失效了,当联合索引跳过中间索引时会造成部分索引失效

2、第二个索引字段和第三个索引字段查询执行

mysql> explain select * from city where  CountryCode='VIR' and District='Manicaland';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | city  | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 4079 |     1.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

key:null 未使用到索引,
key_len:null
跳过第一个字段索引未遵守联合索引最左前缀法则,造成CountryCode、District索引已失效,

思考

 explain select * from city where  District='Manicaland' and Name='Nablus' and  CountryCode='PSE';
+----+-------------+-------+------------+------+-------------------------------+-------------------------------+---------+-------------------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys                 | key                           | key_len | ref               | rows | filtered | Extra                 |
+----+-------------+-------+------------+------+-------------------------------+-------------------------------+---------+-------------------+------+----------+-----------------------+
|  1 | SIMPLE      | city  | NULL       | ref  | idx_Name_CountryCode_District | idx_Name_CountryCode_District | 232     | const,const,const |    1 |   100.00 | Using index condition |
+----+-------------+-------+------------+------+-------------------------------+-------------------------------+---------+-------------------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

总结:执行查询时只要遵守联合索引最左前缀法则和索引查询时的前后位置无任何关系!联合索引遵守idx_Name_CountryCode_District顺序,和 explain select * from city where District=‘Manicaland’ and Name=‘Nablus’ and CountryCode=‘PSE’;无关系,只要查询中遵守最左前缀法则即可

http://www.lryc.cn/news/173945.html

相关文章:

  • LeetCode75-06:移动零
  • C/C++统计满足条件的4位数个数 2023年5月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析
  • python+nodejs+php+springboot+vue 校园安全车辆人员出入安全管理系统
  • 针对discuz3.2的渗透测试
  • python的中秋之美
  • ClickHouse与Elasticsearch比较总结
  • 辅助驾驶功能开发-功能对标篇(12)-NOA领航辅助系统-合众
  • Vue项目中使用element-plus的el-table组件-组件使用-样式修改
  • JavaBean字符串训练(支票大写)
  • Java 核心技术卷 I —— 第2章 Java 编程环境
  • 外汇天眼:英国FCA引入新规定,强化金融广告审核标准!
  • 【python】Seaborn画热力图,只显示第一行数字---seaborn与matplotlib版本问题
  • VMware CentOS7 Docker入门
  • C++ Primer 第5章 语句
  • 【C++】bitset位图的简单模拟实现及常见面试题
  • 十六、MySql的MVCC机制CONNECT(收官!)
  • 194、SpringBoot -- 下载和安装 Erlang 、 RabbitMQ
  • Linux0.11——第二回 从0x7c00到0x90000
  • 封装了一个中间放大效果的iOS轮播视图
  • 趣解设计模式之《小王的糖果售卖机》
  • Redis 哨兵模式模式搭建教程
  • 41. Linux系统配置FTP服务器并在QT中使用QFtp实现文件上传
  • 【新版】系统架构设计师 - 案例分析 - 架构设计<架构风格和质量属性>
  • C++ - 红黑树 介绍 和 实现
  • 【蓝桥杯选拔赛真题62】Scratch判断小球 少儿编程scratch图形化编程 蓝桥杯选拔赛真题解析
  • Spring面试题15:Spring支持几种bean的作用域?singleton、prototype、request的区别是什么?
  • Spring Boot中Tomcat服务器参数解析及高并发控制
  • Python 运行代码
  • 【ROS入门】使用 ROS 话题(Topic)机制实现消息发布与订阅及launch文件的封装
  • 【企业级SpringBoot单体项目模板 】——Mybatis-plus自动代码生成