常见面试题11

简介: MySQL索引主要使用B+tree结构,具有层级少、检索快、支持范围查询等优点。InnoDB中聚簇索引将数据存于叶子节点,主键为默认索引;二级索引则存储主键值,需回表查询完整数据。创建索引需遵循最左前缀、避免类型转换、函数操作等原则,并通过explain分析执行计划,防止索引失效,提升查询效率。

MySQL数据库索引的数据结构?

  • 必答内容:

在MySQL中的索引类型有多种哈,比如像B+tree索引、Hash索引等,但在InnoDB存储引擎中默认使用的是B+tree的索引。

  • 可能继续追问的问题:

B+tree索引结构的特点是什么?

  • B+tree呢,也叫多路平衡搜索树,也就是一个节点中可以存储多个key,多个key,也就对应多个指针,大数据量的情况下,树的高度更低。(树的阶数更多,高度更低,检索更快)。
  • 在B+tree中,所有的数据都是存放在叶子节点的,非叶子节点,仅仅起到索引数据的作用。
  • 而在B+tree的叶子节点中,形成了一个双向链表,便于区间范围查询。

知道什么是聚簇索引,什么是二级索引吗?

  • 必答内容:

这个还是比较清楚的,因为这个是我们在项目中进行SQL语句优化的理论基础。

聚簇索引,有时候也称为聚集索引,他的特点呢就是数据与索引存放在一块儿,B+tree的叶子节点保存了整行数据,而且在一张表中,聚簇索引有且仅有一个,默认主键索引就是聚簇索引。

二级索引,有时候也称为非聚簇索引 或 辅助索引,指的是数据和索引分开存储,B+tree的叶子节点保存对应的主键,二级索引在一张表中可以有多个。

  • 进阶内容(细节):

那刚才提到,默认主键索引就是聚簇索引;虽然在项目开发中我们建议每一张表都必须要添加一个主键,但是从数据库本身来说,一张表是可以没有主键的,那如果没有主键,MySQL数据库会自动的选择第一个非空的唯一索引作为聚簇索引;而如果一张表既没有主键,又没有唯一索引,那这个时候MySQL数据库又会自动生成一个rowID作为聚簇索引。简单说,一张表必须有且仅有一个聚簇索引。

所以,从这个角度讲,在二级索引的叶子节点中存储的其实是对应的聚集索引的值(如果有主键,就是主键值;没有主键,有非空的唯一索引,那就是唯一索引的值;如果既没有主键,也没有非空的唯一索引,那就是自动生成的rowID的值)。

什么是回表查询 ?

  • 必答内容:

在MySQL默认的InnoDB存储引擎中,有两类索引,分别是:聚簇索引和二级索引。 聚簇索引,他的特点呢就是数据与索引存放在一块儿,B+tree索引结构的叶子节点保存了整行数据,而且在一张表中,聚簇索引有且仅有一个,默认主键索引就是聚簇索引。二级索引,指的是数据和索引分开存储,B+tree的叶子节点保存对应的主键,二级索引在一张表中可以有多个。

所谓回表查询,就指的是,在执行这条SQL语句的时候,先根据二级索引去检索出对应的主键值;然后再根据主键值,到聚簇索引中查询出对应的数据,这个过程就叫回表查询。 所以回表查询,是需要扫描两次索引的,性能相对来说会差一些。

  • 进阶内容:

所以,在项目开发中,我们进行SQL优化的时候,如果需求允许的情况下,尽量避免回表查询,主要从以下几个方面来做:

1). 业务允许的情况下,尽可能根据主键查询,使用聚集索引-避免回表查询。

2). 为表中的字段,根据业务需求创建合适的联合索引,查询时使用索引覆盖-避免回表查询。

3). 使用索引下推,减少回表查询的次数。【索引下推,是mysql5.6之后提供的功能】

  • 可能继续发问的问题:

你刚才提到索引下推,简单聊聊什么是索引下推?

索引下推(Index Condition Pushdown),是MySQL5.6后提供的功能,指的是在多条件查询SQL执行时,提前判断对应的搜索条件是否满足,满足了再去回表(就是将本应该在 server 层进行筛选的条件,下推到存储引擎层来进行筛选判断,这样能有效减少回表),通过减少回表次数进而提高查询效率。

为什么MySQL索引结构是B+tree ?

  • 必答内容:

其实这个问题,我们可以做一个假设啊。

  • 假设索引结构是二叉搜索树、平衡二叉树 或 红黑树等,其实本质都是二叉树,一个节点下最多只能有两个子节点,如果这张表要存储的数据量比较大,二叉树的层级将会非常深,检索效率会很低。
  • 而如果索引结构是Btree,在B树中,非叶子节点和叶子节点既要要存储key和指针,还要存放数据,而InnoDB的物理存储结构中,一页(Page)的大小是固定的,就是16KB。 那这一页中能够存储的key的数量并不多,就会造成大数据量情况下,树的层级较深,检索速度慢。 还有一个问题,就是由于 非叶子节点和叶子节点既要要存储key,还要存放数据,查找效率并不稳定。 (有些数据,只需要一次查找,有些数据,可能需要五六次,有些...)

所以,在MySQL数据库中才使用了B+tree作为索引的数据结构。 主要有以下优势:

  • 在B+tree中,非叶子节点并不存放数据,只存放key和指针,所以一页(Page)中能够容纳的key将更多,相同数据量的情况下,树的层级要浅的多,检索效率高。
  • 所有的数据都存储在B+tree的叶子节点中,也就意味着无论什么数据,都需要找到叶子节点才能查询到对应的数据,检索效率更加稳定。
  • 第三是B+树数据都存储在B+tree的叶子节点,并形成了一个双向链表,便于区间范围查询。
  • 可能继续发问的问题:

那MySQL的B+tree的索引结构,树的高度一般是多高呢?

嗯,这个高度其实是可以计算出来的,一般高度在2-3层,如果高度为3,基本上就可以容纳一两千万的数据了。如何计算呢?

  • 我们的索引是在页(Page)中存储的,而一个页的大小模式为(16KB)。
  • 对于非叶子节点来说,页中存储的除了具体的key之外,还有一个就是指针 。(假设主键为bigint占8个字节,指针占6个字节)
  • 那么我们就可以大概计算出一页中可以存储的key数量为:16 * 1024 / 14 = 1170 。也就意味着一个页(Page)中约可以存1170个key
  • 假设一行数据的大小为1KB,一页可以存16条数据。那两层的B+tree可以容纳:1170*16=18720条数据。
  • 那三层的B+tree可以容纳:1170 * 1170 * 16 = 21902400 条数据。

索引创建的原则 ?

  • 必答内容:

好的,我们知道索引确实可以提高查询的效率,但前提是需要针对于数据库表创建合适的索引。创建索引的时候,主要考虑一下几点原则:

1). 针对于数据量较大,且查询比较繁琐的表创建索引。(单表超过10w记录)

2). 针对于经常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。

3). 尽量选择为区分度高的列建立索引,如果该字段是唯一的,建立唯一索引,效率更高。(区分度越高,效率越高)。

4). 在varchar类型的字段上,建议指定索引长度(建立前缀索引),没必要对全字段建立索引,根据实际文本区分度决定索引长度就可以。

5). 尽量建立联合索引,而且在联合索引中将区分度高的字段放在前面,减少单列索引。(查询时,联合索引很多时候可以索引覆盖,避免回表,提高效率)

6). 在满足业务需求的前提下,建立适当的索引,索引不宜过多。(索引过多,会增加维护索引的成本,影响增删改的效率)

简单聊聊索引失效的场景 ?

  • 必答内容:

好的,索引失效这个问题,确实是在项目开发中非常常见的一类问题。那我就结合我之前的项目经验来聊一下,之前遇到的一些索引失效的场景:

  • 第一类呢,就是在联合索引使用的时候,违反最左前缀法则,比如查询的条件并不是从索引最左边的列开始的。
  • 第二类呢,就是范围查询(非等值查询)右侧的列,不能使用索引。
  • 第三类呢,就是在索引列上进行运算或函数操作,索引将失效。非常典型的,像我们基于substring这样的函数截取字段值。
  • 以及如果在条件匹配时,需要进行隐式类型转换的时候。比如:where gender = 1,而gender是char类型,这种字符串不加引号,虽然查也能查出来,但也会造成索引失效。
  • 还有像常见的,以 % 开头的like模糊匹配,索引也会失效。

当然这样的场景很多啊,上面这几个只是比较常见的索引失效的场景,所以在项目开发中,编写SQL时,就要避免这些情况的发生。

  • 进阶内容:

而对于索引是否生效,到底走哪个索引,以及具体SQL语句的执行性能到底怎么样。 这个我们可以借助于 explain 来查看sql语句的执行计划 ,具体问题具体分析。

我们可以通过explain执行计划中的 key 来确定此次查询是否使用了索引,以及通过 type 来判定SQL的执行性能,一定要规避 type 为all全表扫描的情况,还有像 extra 的信息也需要关注一下。


目录
相关文章
|
3月前
|
SQL 存储 分布式计算
【万字长文,建议收藏】《高性能ODPS SQL章法》——用古人智慧驾驭大数据战场
本文旨在帮助非专业数据研发但是有高频ODPS使用需求的同学们(如数分、算法、产品等)能够快速上手ODPS查询优化,实现高性能查数看数,避免日常工作中因SQL任务卡壳、失败等情况造成的工作产出delay甚至集群资源稳定性问题。
1099 36
【万字长文,建议收藏】《高性能ODPS SQL章法》——用古人智慧驾驭大数据战场
|
存储 NoSQL Java
蚂蚁金服Java研发岗二面:redis 常见数据结构以及使用场景分析
redis简单来说 就是一个数据库,不过与传统数据库不同的是 redis 的数据是存在内存中的,所以存写速度非常快,因此 redis 被广泛应用于缓存方向。另外,redis 也经常用来做分布式锁。redis 提供了多种数据类型来支持不同的业务场景。除此之外,redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。所以在面试中我们经常可以看到redis的身影,今天给大家带来一道redis的面试真题以及解析,后面会给大家分享今年来redis常考试的一些真题。
318 0
|
存储 容器
Collectors.groupingBy分组后乱序问题
Collectors.groupingBy分组后乱序问题
|
3月前
|
消息中间件 存储 Java
常见面试题02
本内容介绍MQ的应用场景、交换机模式、消息不丢失机制、延迟消息处理及消息挤压解决方案,涵盖RabbitMQ的确认机制、持久化、消费者配置及实际项目应用。
133 1
|
2月前
|
数据库 微服务
常见面试题19
BASE理论提出“基本可用、软状态、最终一致性”,是分布式系统中对CAP定理的实践妥协。相比强一致的刚性事务(ACID),它属于柔性事务,强调高可用与最终一致,适用于Seata等分布式事务方案中的AT、TCC、SAGA模式,而非传统2PC的强一致性。
72 7
|
3月前
|
缓存 搜索推荐 算法
常见面试题09
排序算法分为比较类(如快排、归并、堆排)和非比较类(如计数、桶、基数)。快排平均最快但不稳定,归并稳定且复杂度恒定,插入排序适合小规模或近有序数据。工业级常混合多种算法优化性能。
96 2
|
3月前
|
传感器 数据可视化 算法
基于卡尔曼滤波的船舶运动控制仿真实现
基于卡尔曼滤波的船舶运动控制仿真实现,包含三自由度运动模型构建、滤波算法实现及可视化代码
98 6
|
3月前
|
存储 网络协议 关系型数据库
常见面试题10
HTTP是超文本传输协议,基于TCP,规定客户端与服务器通信规则。常见请求方式有GET和POST,区别在于参数传递、安全性和用途。HTTPS通过SSL加密更安全,但耗资源。常用状态码如200成功、404未找到、500服务器错误。转发在服务端完成,重定向由浏览器发起两次请求。MySQL中char定长、varchar变长;事务具ACID特性,隔离级别解决并发问题。
111 3
|
3月前
|
供应链 算法 Java
【柔性作业车间调度问题FJSP】基于非支配排序的多目标小龙虾优化算法求解柔性作业车间调度问题FJSP研究(Matlab代码实现)
【柔性作业车间调度问题FJSP】基于非支配排序的多目标小龙虾优化算法求解柔性作业车间调度问题FJSP研究(Matlab代码实现)
148 1
|
3月前
|
设计模式 Java
JAVA基础day08
本笔记系统梳理Java面向对象高级特性,涵盖接口、抽象类、多态、内部类、包、访问修饰符、final与static关键字及单例、工厂等设计模式,助力深入掌握Java核心编程思想。(238字)
154 1