我们在使用数据库的时候,为了增加访问速度,经常会给某张表增加一些索引。单列索引我之前已经写过一篇文章提过,今天我们主要讲一下怎么使用多列索引,和多列索引的最左前缀原则。

关于最左前缀的误解

早些年读高性能mysql这本书的时候,当年感觉书中对于最左前缀的描述相对来说晦涩一点,并且没有详细的例子来说明具体什么是最左前缀,所以在一段时间内我都以为where还要按照顺序写才能触发最左前缀,其实并不是这样。

假设表结构如下

CREATE TABLE `testindex` (`id` int(10) NOT NULL AUTO_INCREMENT,`name` varchar(25) NOT NULL DEFAULT '',`age` int(10) NOT NULL DEFAULT '0',`sex` tinyint(1) NOT NULL DEFAULT '1',PRIMARY KEY (`id`),KEY `multi_index` (`name`,`age`,`sex`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

测试数据:

INSERT INTO `test`.`testindex` (`id`, `name`, `age`, `sex`) VALUES ('1', 'zhangsan', '20', '1');
INSERT INTO `test`.`testindex` (`id`, `name`, `age`, `sex`) VALUES ('2', 'zhangsan', '20', '0');
INSERT INTO `test`.`testindex` (`id`, `name`, `age`, `sex`) VALUES ('3', 'zhangsan', '19', '1');
INSERT INTO `test`.`testindex` (`id`, `name`, `age`, `sex`) VALUES ('4', 'zhangsan', '19', '0');
INSERT INTO `test`.`testindex` (`id`, `name`, `age`, `sex`) VALUES ('5', 'lisi', '20', '1');
INSERT INTO `test`.`testindex` (`id`, `name`, `age`, `sex`) VALUES ('6', 'lisi', '20', '0');
INSERT INTO `test`.`testindex` (`id`, `name`, `age`, `sex`) VALUES ('7', 'lisi', '19', '1');
INSERT INTO `test`.`testindex` (`id`, `name`, `age`, `sex`) VALUES ('8', 'lisi', '19', '0');

这个表中,定义了一个多列索引(组合索引)名字为multi_index,分别由name,age,sex三个字段组成,那么如下几条语句是否会有差异呢:

select id from testindex where name ='zhangsan' and age = 20 and sex = 1;
select id from testindex where name ='zhangsan' and sex = 1 and age = 20;
select id from testindex where age = 20 and name ='zhangsan' and sex = 1;

使用explain来查看一下

EXPLAIN select id from testindex where name ='zhangsan' and age = 20 and sex = 1;
EXPLAIN select id from testindex where name ='zhangsan' and sex = 1 and age = 20;
EXPLAIN select id from testindex where age = 20 and name ='zhangsan' and sex = 1;

三条语句输出的结果一模一样,都是使用了multi_index,事实证明,mysql并不以字段在where中出现的先后顺序来判断是否触发多列索引。实际上我们想一下,mysql也不会做那么不灵活的功能出来。

最左前缀是说的什么顺序

最左前缀其实说的是,在where条件中出现的字段,如果只有组合索引中的部分列,则这部分列的触发索引顺序,是按照定义索引的时候的顺序从前到后触发,最左面一个列触发不了,之后的所有列索引都无法触发。这句话有点绕,我们来以上面三列的组合索引举例子,其索引中包含了三列

  • name
  • age
  • sex

mysql在多列索引的时候不按照where的先后顺序,那么排列组合只有三种 如下:

# 1.where中包含name age(谁放前面无所谓)
EXPLAIN select id from testindex where name ='zhangsan' and age = 20;
# 2.where中包含name sex(谁放前面无所谓)
EXPLAIN select id from testindex where name ='zhangsan' and sex = 1;
# 3.where中包含age sex(谁放前面无所谓)
EXPLAIN select id from testindex where age =20 and sex = 1;

其中3就没有使用索引了,也就是说索引顺序是(name,age,sex)的手,where条件中如果没有name,即使有age和sex字段也不能触发索引。其扫描的条数是8行

那应该会有人想问,那如果有name和sex,中间跨过了age,是能触发索引呢,还是不能触发索引呢。答案是能!但是只能使用name部分的索引来过滤数据。

在explain中的rows中证明了这一点,其中1的扫描行数是2行,2的扫描行数是4行。就是因为没有使用到sex这一列。

最左前缀的后置模糊搜索

EXPLAIN select id from testindex where name like 'zhang%' and age = 20;

explain的结果证明,扫描行数为4行。也就是说如果使用了like这种不完全匹配的,后面的索引就失效了。为了针对这种类似的情况,mysql5.6之后,除了一种新功能叫索引下推。这个以后再进行介绍。

索引覆盖

有那么一种情况下,你想要查询的所有列,已经包含在你的组合索引的字段中,本来二级索引是只存储了索引数据和主键,如果需要的数据索引中不能满足,就需要回表查询数据。而这种索引覆盖了所有想要的列的情况,就就不需要再回表查询具体的数据。这就是索引覆盖。

innodb组合索引的最左前缀原则相关推荐

  1. 数据库性能优化1——正确建立索引以及最左前缀原则

    1. 索引建立的原则 用于索引的最好的备选数据列是那些出现在WHERE子句.join子句.ORDER BY或GROUP BY子句中的列. 仅仅出现在SELECT关键字后面的输出数据列列表中的数据列不是 ...

  2. 数据库正确建立索引以及最左前缀原则

    数据库正确建立索引以及最左前缀原则 转自:https://blog.csdn.net/zhanglu0223/article/details/8713149 1. 索引建立的原则 用于索引的最好的备选 ...

  3. 正确建立索引以及最左前缀原则

    1. 索引建立的原则 用于索引的最好的备选数据列是那些出现在WHERE子句.join子句.ORDER BY或GROUP BY子句中的列. 仅仅出现在SELECT关键字后面的输出数据列列表中的数据列不是 ...

  4. mysql索引优化原则:覆盖索引、最左前缀原则、索引下推

    文章目录 前言 round1:覆盖索引 round2:最左前缀原则 round3:索引下推 小结 前言 在文章开始前,小编提出几个问题,读者可以思考一下如何回答.如果对于以下的问题,回答的模棱两可甚至 ...

  5. 《MySQL实战45讲》——学习笔记04-05 “深入浅出索引、最左前缀原则、索引下推优化“

    04 | 深入浅出索引(上) 1. 什么是索引? 索引的出现其实就是为了提高数据查询的效率,就像书的目录一样,书有500页,每页存的都是书的内容,目录可能只有5页,只存了页码:通过目录能快速找到某个主 ...

  6. 【MySQL】索引原理(三):联合索引(最左前缀原则),覆盖索引,索引条件下推

    准备工作,下面的演示都是基于user_innodb表: DROP TABLE IF EXISTS `user_innodb`; CREATE TABLE `user_innodb` (`id` big ...

  7. 7.联合索引(最左前缀原则)

    1)什么是联合索引? 联合索引指的是对一张表上的多个列进行索引.也就是说,表上多个列加起来组成一个索引,供快速查询使用. 2)如何使用联合索引? 首先,给表添加索引 创建表时给表添加: CREATE ...

  8. 索引原理:联合索引(最左前缀原则)

    准备工作,创建数据表user_innodb表 DROP TABLE IF EXISTS `user_innodb`; CREATE TABLE `user_innodb` (`id` bigint(6 ...

  9. mysql非聚集索引区间查询_mysql的聚集索引和非聚集索引,回表查询,索引覆盖,最左前缀原则略解...

    什么是聚集索引和非聚集索引 我们知道 Mysql 底层是用 B+ 树来存储索引的,且数据都存在叶子节点.对于 InnoDB 来说,它的主键索引和行记录是存储在一起的,因此叫做聚集索引(clustere ...

最新文章

  1. java程序无法连接redis_无法使用jedis连接到redis
  2. android面试自定义view,资深面试官:自定义View的实现方式,你知道几种?
  3. ebs java并发_EBS中Java并发程序笔记(1)
  4. Oracle分析函数四——函数RANK,DENSE_RANK,FIRST,LAST…
  5. git 未能顺利结束(退出码1)
  6. 小小算法题(CCF)
  7. EXT学习经验分享:深刻理解EXT与服务器端的交互
  8. C++static类静态成员函数及变量解析
  9. 给定一个数组,寻找次大的数 (1)
  10. 王道书 P150 T18(在中序线索二叉树里找指定节点在后序的前驱节点)+ 拓展(在中序线索二叉树里找指定节点在先序的后继节点)
  11. Frank-Wolfe和梯度投影方法MATLAB实现
  12. 洛达悦虎1562M各个版本固件升级教程
  13. 2020李宏毅学习笔记——15.Recurrent Netural Network 上
  14. 喜讯|大脑营行苏引华荣获巨量引擎2023全民悦读会“悦读星推官”
  15. (四)Python小甲鱼入门教程笔记——思维导图训练
  16. python文件查重并合并_用python对excel查重
  17. 用数学归纳法证明n阶无向树T有n-1边
  18. 【Tensorflow】卷积层
  19. 什么是 PKI? 公钥基础设施的定义和指南
  20. 数据分析 第一讲 Python语言及工作环境准备、本地数据的采集与操作

热门文章

  1. MySQL 数据表的关联关系 --- 一对一关联
  2. poi 解析中文_百度地图周边最近的POI查询并且解析出中文地址
  3. 利用AidLux实现热成像电力巡检项目-lesson3
  4. 下拉框中select的onclick和onchange两个事件的区别
  5. Python异常名称、警告
  6. 2D格斗游戏的巅峰,精美的像动画一般,IGN评测9分的神作
  7. Tomcat 嵌入式开发 (二) 嵌入式启动 Tomcat
  8. 大数据赋能!天九共享集团打造“抱团三部曲”
  9. (146)FPGA高扇出信号优化方法(一)
  10. 给ESP8266下载程序