准备工作,创建数据表user_innodb表

DROP TABLE IF EXISTS `user_innodb`;
CREATE TABLE `user_innodb` (`id` bigint(64) NOT NULL AUTO_INCREMENT,`name` varchar(255) NOT NULL,`gender` tinyint(1) NOT NULL,`phone` varchar(11) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

联合索引与最左前缀原则

在平时开发中,最常见的是单列索引(比如主键primary id),但是在需要多条件查询的时候,也会创建联合索引。单列索引也可以看成特殊的联合索引。比如在user表中,给name和phone建立一个联合索引。

ALTER TABLE 可以用来创建索引,包括普通索引、UNIQUE索引或PRIMARY KEY索引:

ALTER TABLE table_name ADD INDEX index_name (column_list)

ALTER TABLE table_name ADD UNIQUE (column_list)

ALTER TABLE table_name ADD PRIMARY KEY (column_list)

ALTER TABLE user_innodb add INDEX comidx_name_phone(name,phone); -- 创建联合索引

1.1 联合索引的组织

下图是B+树的索引结构,是一个单值索引:

可以看出,所有非叶子节点的构成都是由两部分组成,索引值+指针,而单值索引说的就是在索引值这里只有一个值(比如id),而联合索引在索引值可能会有多个值(比如name和phone)

与单值索引的不同

  1. 联合索引在B+树中是复合的数据结构
  2. 由于B+树本身是有序的,所以联合索引是从左到右的顺序来建立搜索树的(name在左边,phone在右边)。从上图可以看出,name是有序的,phone是无序的。当name相等时,phone才是有序的。
  3. 当存储引擎是innoDB时,叶子节点存储的是数据/主键

Q1:联合索引如何查找数据?
比如,使用where name = ‘zhangsan’ and phone='1320xx’去查询数据的时候

  1. B+树会优先比较name来确定下一步应该搜索的方向,往左还是往右
  2. 如果name相同的时候就比较phone

但是如果查询条件没有name,就不知道第一步应该查询哪个节点,因为建立搜索树的时候name是第一个比较因子,所以用不到索引。
Q2:联合索引与单值索引的关系?
假设项目里有两个查询很慢:

SELECT * FROM user_innodb WHERE name= ?;
SELECT * FROM user_innodb WHERE name= ? AND phone=?;

按照我们的想法,一个查询创建一个索引,所以针对这两条SQL创建两个索引,这种做法觉得正确吗?

CREATE INDEX idx_name on user_innodb(name);
CREATE INDEX idx_name_phoneonuser_innodb(name,phone);

当我们创建一个联索引的时候,用左边的字段name去查询的时候,也能用到索引,所以单独为name创建一个索引完全没必要,相当于建立了两个联合索引(name),(name,phone)
如果创建三个字段的索引index(a,b,c)相当于创建三个索引:index(a),index(a,b),index(a,b,c)。用where b=?和where b=? and c=? 和where a = ? and c = ?是不能使用到索引。以为不能不用第一个字段,也不能中断。

1.2 最左前缀原则

因为联合索引中包含了多个字段,所以不能像单值索引那样直接使用,需要遵守规则?
就是最左前缀原则:带头大哥不能死,中间兄弟不能断

1.建立索引时,一定要把常用的列放在最左边。比如下面三个语句,能用到联合索引吗?
使用两个字段,可以用到联合索引(注:两个字段的顺序颠倒并不影响,因为全值匹配时mysql会优化字段顺序)

EXPLAIN SELECT * FROM user_innodb WHERE name= '张三' AND phone='12345678910'

2.使用左边的name字段,可以用到联合索引:

EXPLAIN SELECT * FROM user_innodb WHERE name= '张三'

3.使用右边的phone字段,无法使用索引,全表扫描:

EXPLAIN SELECT * FROM user_innodb WHERE name= '12345678910'

不要在索引上做任何操作,因为可能会导致索引失效,转而全表扫描

1.3 索引失效的情况

  1. 使用函数,表达式,计算(加减乘除)。因为当前值改变后无法与索引存的值匹配
SELECT * FROM user_innodb where left(name, 3)='张三';-- left函数是一个字符串函数,它返回具有指定长度的字符串的左边部分
  1. 使用范围查询会导致右边列失效。因为二叉树的查找是=查找,若是一个范围的话无法继续下探
SELECT * FROM user_innodb where name='张三' and age > 22;
  1. like以通配符开头,mysql索引失效会变成扫描操作。因为无法判断%代表多少字符。
SELECT * FROM user_innodb where name like '%三';
  1. 字符串不加’ '索引失效。因为会出现出现隐式转换,相当于给索引列做了操作
SELECT * FROM user_innodb where name = 007;-- "007"从字符串变成了数字007
  1. 少用or,用它连接时很多情况下索引会失效
SELECT * FROM user_innodb where name = '张三' or name = '李四';
  1. is null,is not null 无法使用索引.
SELECT * FROM user_innodb where name is null;

==> 对这一部分内容通过一首打油诗做个总结:

                     全值匹配我最爱,最左前缀要遵守带头大哥不能死,中间兄弟不能断索引列上少计算,范围之后全失效like百分写最右,覆盖索引不写星不等空值还有or,索引失效要少用

原文参考:https://blog.csdn.net/weixin_43935927/article/details/109361168

索引原理:联合索引(最左前缀原则)相关推荐

  1. 【MySQL】索引优化中的最左前缀原则和索引下推

    目录 一.引入 二.覆盖索引 ​ 讲接下来的问题前首先讲一下联合索引的底层存储结构长什么样?联合索引的检索过程是什么样的呢? 三.最左前缀原则 最左前缀原则的定义 四.索引下推 五.小结 一.引入 在 ...

  2. mysql索引最左前缀原则

    mysql索引最左前缀原则 创建索引可以大大提高系统的性能. 第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性. 第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因. 第三, ...

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

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

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

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

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

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

  6. Mysql中的复合索引(联合索引)原理

    联合索引原理 联合索引,通过顺序比较对应的值,来实现排序和查找.对于每一个联合索引所在页,都包含对应参与联合索引列的值,和指向子节点的指针. create index idx_T1_abc on T1 ...

  7. 我去,为什么最左前缀原则失效了?

    问题 最近,在 mysql 测试最左前缀原则,发现了匪夷所思的事情.根据最左前缀原则,本来应该索引失效,走全表扫描的,但是,却发现可以正常走索引. 表结构如下( Mysql 版本 5.7.22): C ...

  8. mysql 索引 原理_MySQL索引实现原理分析

    目前大部分数据库系统及文件系统都采用B-Tree(B树)或其变种B+Tree(B+树)作为索引结构.B+Tree是数据库系统实现索引的首选数据结构.在MySQL中,索引属于存储引擎级别的概念,不同存储 ...

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

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

最新文章

  1. 你算个什么鸟?AI十级“找茬”选手诞生
  2. ListView图片不显示 Application.EnableVisualStyle bug
  3. 不想工作就想创业?我劝你看完这档综艺再决定
  4. java多线程的实现方式_Java 多线程(一)——多线程的实现方式
  5. Linux 火狐浏览器安装Flash插件
  6. Major GC 是清理老年代。 Full GC 是清理整个堆空间—包括年轻代和老年代。
  7. Audiophobia(Floyd算法)
  8. 蓝桥杯-----历届试题 小数第n位
  9. java计算机毕业设计小型企业财务报销管理源码+lw文档+系统+数据库
  10. C. Mortal Kombat Tower(动态规划)Educational Codeforces Round 95 (Rated for Div. 2)
  11. 【ACM】算法竞赛及OJ题面常用英文单词整理(更新ing)
  12. 60著名条原则和定理
  13. U-Boot 之三 详解使用 eclipse + J-Link 进行编译及在线调试
  14. 常见的一些代码编辑器
  15. fatal: unable to connect to gitlab.domian: gitlab.domian : Temporary failure in name resolution
  16. avi怎么转换为mp4格式?
  17. spring同一个类中,一个方法调用另外一个注解(@Transactional)方法时,注解失效
  18. 7.28 结构体 Day18
  19. Hydra – Brute Force HTTP(S)
  20. PostgreSQL 10.0 preview 主动防御 - 禁止执行全表删除、更新(可配置)

热门文章

  1. 为什么要配置JDK的环境变量?和配置JDK环境变量的步骤个人总结
  2. #千锋逆战班,ssf# 在千锋“逆战”学习第 18天, 每个人生阶段都需要努力去扮好自己的角色,越努力越轻松,越坚强越幸运! 加油
  3. 江小白包装设计原型_从“江小白”酒谈品牌外包装设计欣赏趋势
  4. 别再用定时任务来关闭超时订单了
  5. 《寒战》看完整部电影的最大感觉竟然是没看懂
  6. python如何创建二维数组
  7. 双网双待 玫瑰金镶边 酷派奢华旗舰N900+图赏
  8. 查看Apache服务器的错误log文件
  9. linux 镜像 安装rabbitmq
  10. 计算机网络重要协议汇总及解释笔记