百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

MySQL 高频面试题—索引

csdh11 2024-11-30 19:56 27 浏览

前言

谈到索引大家并不陌生,其目的就是为了提高查询效率,用一句话概括就是排好序的数据结构,MySQL中索引主要通过B+tree 实现,对B+tree感兴趣的可以看我上一篇文章。为了对索引有更深层次的了解,下面从以下几个方面介绍索引。

一、索引的分类

1.从存储结构上划分为:BTree索引(BTree或B+Tree索引)、Hash索引、全文索引、空间数据索引,其中B+Tree索引是我们最常用到的。

2.从应用层面分为:普通索引,唯一索引,主键索引,复合索引。

  • 普通索引:建立在普通字段上,没有任何限制;
  • 唯一索引:与“普通索引”相似,不同的是索引字段必须是唯一的,允许有空值;
  • 主键索引:主键索引是特殊的唯一索引,建立在主键字段上,不允许有空值存在;
  • 复合索引:又称组合索引,由多个字段组合建立的索引,复合索引可以代替多个单列索引,相比多个单列索引复合索引所需的开销更小;

3.从存储结构和查询逻辑方面划分:聚集索引,非聚集索引

二、聚集索引和非聚集索引

在 MySQL 数据库中 InnoDB 存储引擎,B+ 树可分为聚集索引和非聚集索引。聚集索引也叫聚簇索引,非聚集索引也叫辅助索引或者二级索引。
建表的时候都会创建一个聚集索引,每张表都有唯一的聚集索引,:

  • 如果主键被定义了,那么这个主键就是作为聚集索引
  • 如果没有主键被定义,那么该表的第一个唯一非空索引作为聚集索引
  • 如果没有主键也没有唯一索引,InnoDB 内部会生成一个隐藏的主键作为聚集索引

二者区别

  1. 聚集索引一张表只能有一个,而非聚集索引一张表可以存在多个;
  2. 聚集索引:索引排序与数据物理顺序一致,具有更快的检索速度,但是新增删除数据会比较慢,需要花费额外的时间进行重新排序来保证与数据物理顺序一致;
  3. 非聚集索引:物理存储不按照索引排序;非聚集索引则就是普通索引了,仅仅只是对数据列创建相应的索引,不影响整个表的物理存储顺序;
  4. 聚集索引叶子节点存储的是整行的数据,非聚集索引叶子节点存储的是主键的值;

三、什么是回表?

了解了聚集索引和非聚集索引,什么是MySQL回表也就不难理解了。假设通过聚集索引来查询数据,例如 select * from tb_name where id=10; 那么只需要搜索其叶子节点就可以找到id等于“10”这行数据。如果是通过非聚集索引来查询数据,例如 select * from tb_name where name='javaboy',那么此时需要先搜索 username 这一列的索引的 B+Tree,搜索完成后得到主键的值,然后再去搜索主键索引的 B+Tree,就可以获取到一行完整的数据。

上述先通过非聚集索引找到主键值,再通过主键去聚集索引查询记录的过程,称为回表查询

四、什么是覆盖索引?

辅助索引查找记录时,索引字段列已经覆盖了查询结果的列,就不需要再通过聚集索引查询完整的记录,这种情况就叫覆盖索引。

举个例子:建立辅助索引 index(name, age),当执行如下SQL:select name, age form t where name = 'zhangsan' and age = '25'; 于索引的节点上保存的索引列的组合name和age, 也就不需要再进行回表查询了。

这也是为什么不建议用select *查询的原因,只返回查询需要的列,当索引字段覆盖了查询需要的列时,也就不需要回表了,可以减少大量io操作提高查询速度。

五、索引在什么情况下失效?

熟悉explain关键字的都知道索引并不是时时都会生效的,比如以下几种情况,将导致索引失效:

  • 查询条件中带有or,除非所有的查询条件都建有索引,否则索引失效;
  • like查询是以%开头;
  • 索引字段使用了函数或者计算;
  • 发生了类型转换;例如:select * from t where no = 20; 当 no类型是字符类型,等号右边为int类型时,执行时会发生隐式类型转换,从而导致索引失效;
  • 不满足最左匹配原则;

最左匹配原则

最左匹配原则又称最左前缀原则,指的是在一个组合索引中(a,b,c),B+ 树会按照从左往右的顺序建立搜索树,B+ 树会优先比较 a,如果 a 相同在依次比较 b 和 c,但是像查询(b,c)这样的数据没有 a 字段,B+树就不知道从哪个结点查起了, 因为搜索树的第一个比较因子就是 a

总结:

由此可见,索引用的好能大大提高查询速度,前提是对索引有足够的了解,否者反而会SQL执行速度,当然索引并不是越多越好,还要根据具体的业务场景来选择,索引适合建立在离散度高的列,也就是重复数据较少的列,像性别只有男和女的列就不适合建立索引。

相关推荐

探索Java项目中日志系统最佳实践:从入门到精通

探索Java项目中日志系统最佳实践:从入门到精通在现代软件开发中,日志系统如同一位默默无闻却至关重要的管家,它记录了程序运行中的各种事件,为我们排查问题、监控性能和优化系统提供了宝贵的依据。在Java...

用了这么多年的java日志框架,你真的弄懂了吗?

在项目开发过程中,有一个必不可少的环节就是记录日志,相信只要是个程序员都用过,可是咱们自问下,用了这么多年的日志框架,你确定自己真弄懂了日志框架的来龙去脉嘛?下面笔者就详细聊聊java中常用日志框架的...

物理老师教你学Java语言(中篇)(物理专业学编程)

第四章物质的基本结构——类与对象...

一文搞定!Spring Boot3 定时任务操作全攻略

各位互联网大厂的后端开发小伙伴们,在使用SpringBoot3开发项目时,你是否遇到过定时任务实现的难题呢?比如任务调度时间不准确,代码报错却找不到方向,是不是特别头疼?如今,随着互联网业务规模...

你还不懂java的日志系统吗 ?(java的日志类)

一、背景在java的开发中,使用最多也绕不过去的一个话题就是日志,在程序中除了业务代码外,使用最多的就是打印日志。经常听到的这样一句话就是“打个日志调试下”,没错在日常的开发、调试过程中打印日志是常干...

谈谈枚举的新用法--java(java枚举的作用与好处)

问题的由来前段时间改游戏buff功能,干了一件愚蠢的事情,那就是把枚举和运算集合在一起,然后运行一段时间后buff就出现各种问题,我当时懵逼了!事情是这样的,做过游戏的都知道,buff,需要分类型,且...

你还不懂java的日志系统吗(javaw 日志)

一、背景在java的开发中,使用最多也绕不过去的一个话题就是日志,在程序中除了业务代码外,使用最多的就是打印日志。经常听到的这样一句话就是“打个日志调试下”,没错在日常的开发、调试过程中打印日志是常干...

Java 8之后的那些新特性(三):Java System Logger

去年12月份log4j日志框架的一个漏洞,给Java整个行业造成了非常大的影响。这个事情也顺带把log4j这个日志框架推到了争议的最前线。在Java领域,log4j可能相对比较流行。而在log4j之外...

Java开发中的日志管理:让程序“开口说话”

Java开发中的日志管理:让程序“开口说话”日志是程序员的朋友,也是程序的“嘴巴”。它能让程序在运行过程中“开口说话”,告诉我们它的状态、行为以及遇到的问题。在Java开发中,良好的日志管理不仅能帮助...

吊打面试官(十二)--Java语言中ArrayList类一文全掌握

导读...

OS X 效率启动器 Alfred 详解与使用技巧

问:为什么要在Mac上使用效率启动器类应用?答:在非特殊专业用户的环境下,(每天)用户一般可以在系统中进行上百次操作,可以是点击,也可以是拖拽,但这些只是过程,而我们的真正目的是想获得结果,也就是...

Java中 高级的异常处理(java中异常处理的两种方式)

介绍异常处理是软件开发的一个关键方面,尤其是在Java中,这种语言以其稳健性和平台独立性而闻名。正确的异常处理不仅可以防止应用程序崩溃,还有助于调试并向用户提供有意义的反馈。...

【性能调优】全方位教你定位慢SQL,方法介绍下!

1.使用数据库自带工具...

全面了解mysql锁机制(InnoDB)与问题排查

MySQL/InnoDB的加锁,一直是一个常见的话题。例如,数据库如果有高并发请求,如何保证数据完整性?产生死锁问题如何排查并解决?下面是不同锁等级的区别表级锁:开销小,加锁快;不会出现死锁;锁定粒度...

看懂这篇文章,你就懂了数据库死锁产生的场景和解决方法

一、什么是死锁加锁(Locking)是数据库在并发访问时保证数据一致性和完整性的主要机制。任何事务都需要获得相应对象上的锁才能访问数据,读取数据的事务通常只需要获得读锁(共享锁),修改数据的事务需要获...