文章目录

  • 前言
    • 最左匹配原则
      • 为什么会有最左前缀呢?
      • 联合索引的存储结构
      • 联合索引字段的先后顺序
      • b+树可以存储的数据条数
  • 总结

前言

​ 对于联合索引我们知道,在使用的时候有一个最左前缀的原则,除了这些呢,比如字段放置的位置,会不会对索引的效率产生影响呢?

  • 最左匹配原则

​ 联合索引时会遵循最左前缀匹配的原则,即最左优先,在检索数据时从联合索引的最左边开始匹配,示例:

create table test
(id       bigint auto_incrementprimary key,column_1 bigint null,column_2 bigint null,column_3 bigint null
);create index test_column_1_column_2_column_3_indexon test (column_1, column_2, column_3);

​ 比如上面的test表,我们建立了联合索引index test_column_1_column_2_column_3_index on test (column_1, column_2, column_3);当我们进行查询的时候,按照最左前缀的原则,当查询(column_1)、(column_1,column_2)(column_1,column_2,column_3)这三种组合是可以用到我们定义的联合索引的。如果我们查询(column_1,column_3)就只能用到column_1的索引了。我们不用太关心索引的先后顺序,什么意思呢?比如使用(column_1,column_2)和(column_2,column_1)的效果是一样的,数据库的查询优化器会自动帮助我们优化我们的sql,看哪个执行的效率最高,
最后才生成最后执行的sql。

为什么会有最左前缀呢?

​ 当使用b+树作为索引的存储数据结构时,当我们创建联合索引的时候,比如(column_1, column_2, column_3),b+树建立索引是从左到右来建立搜索树的,比如当我们来查询的时候WHERE column_1 = 1 AND column_2 = 2 AND column_3 = 3。b+树会先通过最左边的(建立索引的字段的左边的字段)字段,也就是column_1来确定下一步的查找对象,然后找到column_2,在通过column_2的索引找到column_3。所以(column_2,column_3)这样的查询命中不到索引了。因为最左前缀,一定是从最左边的字段开始依次在b+树的子节点查询,然后确定下一个查找的子节点的数据。所以我们(column_1)、(column_1,column_2)、(column_1,column_2,column_3)这三种查询条件是可以使用到索引的。

联合索引的存储结构

​ 定义联合索引(员工级别,员工姓名,员工出生年月),将联合索引按照索引顺序放入节点中,新插入节点时,先按照联合索引中的员工级别比较,如果相同会按照是员工姓名比较,如果员工级别和员工姓名都相同 最后是员工的出生年月比较。可以从图中从上到下,从左到右看,第一个B+树的节点 是通过联合索引的员工级别比较的,第二个节点是 员工级别相同,会按照员工姓名比较,第三个节点是 员工级别和员工姓名都相同,会按照员工出生年月比较。

联合索引字段的先后顺序

​ 我们定义多个字段的联合索引,会考虑到字段的先后顺序。那么字段的先后顺序真的会对查询的效率产生影响吗?比如上面的联合索引

index test_column_1_column_2_column_3_index on test (column_1, column_2, column_3);index test_column_1_column_2_column_3_index on test (column_2, column_1, column_3);在查询效率上有差别吗?我们试验下

写个函数批量插入下数据

CREATE PROCEDURE dowhile()
BEGINDECLARE v1 INT DEFAULT 20000000;WHILE v1 > 0 DOINSERT INTO test.test (column_1, column_2, column_3) VALUES (RAND() * 20000000, RAND() * 10000, RAND() * 20000000);SET v1 = v1 - 1;
END WHILE;
END;

​ 我们插入了20000000条数据,然后先设置索引(column_1, column_2, column_3)中column_1的数值范围为0到20000000,column_2的范围为0到10000。然后查询,看看这个索引的效率。数据量太大,插入的时间可能要好久。为什么插入20000000条呢,因为b+树可以高效存储的数据条数就是21902400,具体见下文。

​ 我们尝试下查询的效率

SELECT * FROM test WHERE column_1=19999834 AND  column_2=3601
> OK
> 时间: 0.001sEXPLAIN SELECT * FROM test WHERE column_1=19999834 AND  column_2=3601

我们看到索引的type为ref已经相当高效了。

​ type:这列最重要,显示了连接使用了哪种类别,有无使用索引,是使用Explain命令分析性能瓶颈的关键项之一。
​ 结果值从好到坏依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
一般来说,得保证查询至少达到range级别,最好能达到ref,否则就可能会出现性能问题。

​ 然后我们看下插入的效率

INSERT INTO test.test (column_1, column_2, column_3) VALUES (RAND() * 20000000, RAND() * 10000, RAND() * 20000000)
> Affected rows: 1
> 时间: 0.002s

​ 更改索引的顺序

drop index test_column_1_column_2_column_3_index on test;create index test_column_2_column_1_column_3_indexon test (column_2, column_1, column_3);

我们把column_2column_1的索引位置更换了一下,来比较联合索引的先后顺序对查询效率的影响。

SELECT * FROM test WHERE  column_2=3601 AND column_1=19999834
> OK
> 时间: 0.001sEXPLAIN SELECT * FROM test WHERE  column_2=3601 AND column_1=19999834

发现更换了之后查询时间上没有什么出入,还和上个查询的时间一样,分析查询的效率一样很高。

再来看插入的效率

INSERT INTO test.test (column_1, column_2, column_3) VALUES (RAND() * 20000000, RAND() * 10000, RAND() * 20000000)
> Affected rows: 1
> 时间: 0.003s

​ 依然高效

​ 所以我们可以总结出来,联合索引中字段的先后顺序,在sql层面的执行效率,差别不大,是可以忽略的。分析上面索引的数据结构也是可以推断出来的,无非就是当建立联合索引,更换索引字段的先后顺序,匹配每个字段锁定的数据条数不一样,但是对最终的查询效率没有太大的影响。但是这个字段的顺序真的就不用考虑吗?不是的,我们知道有最左匹配原则,所以我们要考虑我们的业务,比如说我们的业务场景中有一个字段enterpriseId,这个字段在80%的查询场景中都会遇到,那么我们肯定首选将这个字段放在联合索引字段的第一个位置,这样就能保证查询的高效,能够命中我们建立的索引。

b+树可以存储的数据条数

​ b+树 正常的高度是(1~3)一个整型8b 指针占用6b,mysql页文件默认16K16k的数据可以存储16/14b=1170三层的数据大概就是1170*1170*16=21902400(千万条数据)所以千万级别的数据,对于建了索引的数据库查询的数据库也是很快的。

总结


对于联合索引,我们不能忽略它的最左匹配原则,即在检索数据时从联合索引的最左边开始匹配。对于创建联合索引时,我们要根据我们的具体的查询场景来定,联合索引字段的先后顺序,联合索引字段的先后顺序在sql层面上没有太大差别,但是结合查询的场景和最左匹配的原则,就能使一些查询的场景不能很好的命中索引,这点使我们是不能忽略的。

MySQL创建联合索引,字段的先后顺序,对查询的影响分析相关推荐

  1. mysql创建联合索引_mysql如何创建多个联合索引

    mysql创建多个联合索引的方法:可以使用CREATE INDEX或ALTER TABLE语句来创建.在创建联合索引时,应该仔细考虑列的顺序. MySQL中索引规则: 1.需要加索引的字段,要在whe ...

  2. MySql创建联合索引

    首先创建一个表:create table t1 (id int primary key,username varchar(20),password varchar(20)); 创建单个索引的语法:cr ...

  3. mysql怎样实现先判断后联合_MYSQ创建联合索引,字段的先后顺序,对查询的影响分析...

    MYSQ创建联合索引,字段的先后顺序,对查询的影响分析 前言 对于联合索引我们知道,在使用的时候有一个最左前缀的原则,除了这些呢,比如字段放置的位置,会不会对索引的效率产生影响呢? 最左匹配原则 联合 ...

  4. 高性能Mysql——创建高性能索引详解

    索引(在MySQL中也叫做"键(key)")是存储引擎用于快速找到记录的一种数据结构.这是索引的基本功能,除此之外,本章还将讨论索引其他一些方面有用的属性. 索引对于良好的性能非常 ...

  5. mysql之联合索引

    mysql之联合索引测试: 前期准备: 建立联合索引? CREATE TABLE `test` (`id` bigint(16) NOT NULL AUTO_INCREMENT,`aaa` varch ...

  6. mysql建立联合索引_mysql之联合索引

    mysql之联合索引测试: 前期准备: 建立联合索引? CREATE TABLE `test` ( `id` bigint(16) NOT NULL AUTO_INCREMENT, `aaa` var ...

  7. MySQL数据库联合索引的命中规则

    一.联合索引的使用 本文中联合索引的定义为(MySQL): ALTER TABLE table_name ADD INDEX (col1,col2,col3); 二.联合索引的本质 当创建(col1, ...

  8. mysql 创建覆盖索引_Mysql覆盖索引 covering index 或者 index coverage

    组合索引 提到组合索引,大家都知道"最左前缀"原则.例如,创建索引 idx_name_age (name,age) ,通常情况下,where age=50 或者 where age ...

  9. 2 创建联合索引_想进大厂,这些Mysql索引底层知识你是必须知道的

    推荐学习 阿里P8MySQL,基础/索引/锁/日志/调优都不误,一锅深扒端给你 最新Java岗面试清单:分布式+Dubbo+线程+Redis+数据库+JVM+并发 前言 这一篇是讲解Mysql中做使用 ...

最新文章

  1. centos7安装Metricbeat7.6.0采集nginx指标
  2. 新建parcel写入数据后,读取数据为null
  3. 考研408大纲22年考研
  4. 自己整理的css3动画库,附下载链接
  5. oracle查表占的物理空间,查询Oracle表实际物理使用大小
  6. day7 java的构造器
  7. unrecognized selector sent to instance问题的解决
  8. 实验8.1 链表类的定义与实现
  9. ajax--跨域问题及三种简单的解决方案
  10. 51单片机流水灯现象2
  11. linux洪水攻击软件,Linux遭受SYN洪水攻击设置
  12. 芯片解密STM32F100VB 芯片基本特性
  13. mysql集群 MySQL Cluster
  14. Android逆向之CA证书提取
  15. SUMO无法创建xml文件 Could not build output file
  16. 微信公众号内下载pdf等文件,受微信所限制,安卓和IOS不同处理方式(最最最优版)
  17. 蓝桥杯之Python算法设计系列(二)
  18. 编译项目时pangolin出现莫名其妙的问题
  19. 利用随机森林对特征重要性进行评估 方法一
  20. python中基例是什么意思_python中 *= 是什么意思

热门文章

  1. 如何确定等势面_电势高低的判断方法有哪些
  2. 【代码审计】任意文件读取漏洞实例
  3. Debezium同步之postgres到oracle的同步
  4. 分析paypal 电子礼品卡提交模式
  5. 当代世界经济发展趋势
  6. Android实现Mtp访问浏览手机存储(二) 禁止DocumentsUI文件直接弹出
  7. 猫耳RGB设计观感超萌,还支持7.1声道,硕美科GS510头戴耳机更适合女生
  8. 学生信息管理系统测试计划大纲
  9. 电网中直流潮流Distribution Factor的计算,bus间有多条输电线
  10. mysql关键字与连表操作理论