当前位置: 首页 > news >正文

【浅学Java】MySQL索引七连炮

MySQL索引面试七连炮

  • 0. 谈一下你对索引的理解
  • 1. MySQL索引原理和数据结构能介绍一下吗
  • 2. B+树和B树的区别
  • 3. MySQL聚簇索引和非聚簇索引的区别
  • 4. 使用MySQL索引都有什么原则
    • 4.1 回表
    • 4.2 索引覆盖
    • 4.3 最左匹配
    • 4.4 索引下推
  • 5. 不同的存储引擎是如何进行数据的存储的
  • 6. MySQL组合索引的结构是怎样的
  • 7. MySQL索引是如何进行优化的

0. 谈一下你对索引的理解

首先。MySQL里面存的一些索引,索引的数据结构是通过B+树或者哈希表生成的。

存储引擎:
对于不同类型的索引,是与存储引擎相关的,如果你使用的是Myisam或者Innodb这样的存储引擎,那对应的数据类型就是B+树;如多使用的Memory这种存储引擎,那所使用的数据结构就是哈希表。不同的存储引擎表示的是不同的数据在磁盘上的组织形式。

为什么InnoDB和Myisam要使用B+树呢?
首先,我们得清楚,索引里面存储得是什么。一般情况下,索引里面存储的是Key,通过key去找到对应的value。对于这种key-value形式的数据,我们可以采用的数据结构有很多选择,比如:哈希表、二叉树、AVL树、B+树。

不管使用什么形式的二叉树,它最终都会导致树高度的增高,这就会使io的次数增多,使得整体的io访问的效率降低。而不使用哈希表是因为它不支持范围查找。

选择B+树这样的数据结构之后,他就会尽多的在一个数据节点里面存储数据,让树的高度变低,从而减少io的次数,提高数据访问的效率。

索引分类:
在MySQL里面有主键索引、唯一性索引、普通索引、组合索引、全文索引等各种索引。在日常的开发中,最常用到的可能就是主键索引和组合索引,在使用这两种索引的时候,会存在一系列问题,比如:回表、覆盖索引、最左匹配、索引下推。

在执行SQL语句的时候,可以通过索引的一些点来进行优化,提高我们对于数据的访问效率。

1. MySQL索引原理和数据结构能介绍一下吗

MySQL的索引底层使用B+树来进行数据的存储。
使用B+树的优点:

  1. B+树是一个多叉搜索树,可以进行数据的查找操作
  2. B+树的非叶子节点只存储Key值,这样就可以在一个数据节点里面存储更多的数据,从而降低树的高度,减少IO访问的次数,从而提高数据查询的效率。
  3. B+树的叶子节点存储数据的详细信息,每个数据在叶子节点上都有体现,并且这些叶子节点用链表的形式连接起来,从而支持范围查找。

2. B+树和B树的区别

我们先来看看两种数据结构的数据存储模型图:
在这里插入图片描述
下面来总结一下两者的区别:

  1. B树的键值分布在整个树中;而B+只在叶子节点存储键值,非叶子节点只存储Key值
  2. B+树的叶子节点是以链表的形式进行存储,可以支持范围查询;而B树不行
  3. B+树的数据节点中只存储Key,而B树的数据节点中还存储data,这就意味着B+树单次磁盘 IO 的信息量大于B树,从这点来看B+树相对B-树磁盘 IO 次数少

3. MySQL聚簇索引和非聚簇索引的区别

想要理解聚簇索引和非聚簇索引的区别,那我们先来理解一下下面的这些东西:

对于InnoDB存储引擎,在插入数据的时候,数据必须和索引绑定到一起,索引可以是主键,可以是唯一性键,也可以是6字节的rowid。

在一个表中,可能有多个索引,但是数据只能有一份,不会造成文件的冗余。当数据跟某一个索引列绑定到一起的时候,其他的索引列应该如何检索数据呢?

方法是:将 已经跟数据绑定的索引列的值 放到其他索引的叶子节点。

id为主键时,用主键建立的索引结构:
在这里插入图片描述

而id为主键时,以name建立的索引:
在这里插入图片描述

  1. InnoDB是通过B+树结构对主键创建索引,然后叶子节点存储记录,如果没有主键,就用唯一性键创建索引,如果没有唯一性键,就用6字节的row_id来作为主键创建索引。
  2. 如果创建索引的键是其他字段,那么在叶子节点存储的就是该记录的主键,然后再通过主键索引来找到对应的记录,这就做回表

理解了上面这些,再来谈谈聚簇索引和非聚簇索引:

聚簇索引:索引跟数据放到一起,比如上面的 id
非聚簇索引:索引跟数据没有直接放到一起,需要通过回表才能查询到数据,比如上面的name

还有一个小知识:

  1. 在InnoDB存储引擎当中,既存在聚簇索引,也存在非聚簇索引。
  2. 在myisam存储引擎当中,只存在非聚簇索引,根本原因是:myisam存储引擎索引列单独是一个文件

4. 使用MySQL索引都有什么原则

4.1 回表

从某一个索引的叶子节点拿到聚簇索引的id值,然后再根据id值去聚簇索引里面找到对应的全量信息。设计回表查询的效率不高,一次回表使io次数翻倍,要尽量减少回表。

假设有一个表:id,name,age,gender四个列,id为主键,name为普通索引

当执行 select * from table where name = "zhangsan"时,它得先在name索引中找到主键id的值,然后再去id索引中查询全列信息。

4.2 索引覆盖

从索引的叶子节点中,能获取全量查询列的过程就叫做覆盖索引,覆盖索引不需要再回表。

假设有一个表:id,name,age,gender四个列,id为主键,name为普通索引

当执行 select id,name from table where name = "zhangsan"时,再name索引中,可以查到id,也可以查到name,此时就不需要再进行回表。

4.3 最左匹配

对于组合索引,要遵循最左匹配原则,即:索引的匹配顺序必须是从左向右。

假设有一个表:id,name,age,gender四个列,id为主键,name和age为组合索引

当执行如下语句的时候,那些能用到组合索引?

select * from table where name="zhangsan" and age=10;
select * from table where name="zhangsan";
select * from table where age=10;
select * from table where age=10 and name="zhangsan";

答案是:1,2,4可以使用组合索引。原因如下:

第1个是标准的顺序,没问题
第2个是查询name,符合最左匹配,也没问题
第3个把name跳过了,不符合组合索引的要求
第4个是mysql索引优化器对索引的顺序进行了调整,因为age和name的顺序对查询结果没有影响。

4.4 索引下推

MySQL的组成部门:
在这里插入图片描述

当执行 select * from table where name=“zhangsan” and age=10 时

  1. 在没有索引下推之前:先根据name去存储引擎拿到全量的数据,在将数据读取到server层,然后server层再根据age进行筛选,将最终结果返回给客户端
  2. 有了索引下推之后:直接根据name和age去存储引擎拿到全量数据,然后将最终结果返回给客户端

5. 不同的存储引擎是如何进行数据的存储的

在InnoDB中:
在这里插入图片描述

frm存储表结构相关的东西
ibd存储的是实际的数据

在Myisam中:
在这里插入图片描述

frm存储表结构相关东西
MYD存储数据
MYI存储索引

两者数据的存储的区别:在InnoDB中,数据和索引存储在一起,而在myisam当中,数据和索引分开存储,这也便是myisqm只有非聚簇索引的原因。

6. MySQL组合索引的结构是怎样的

和普通索引就一个区别:key值多为多个,即(key,key)——>value.

7. MySQL索引是如何进行优化的

待沉淀。

http://www.lryc.cn/news/34094.html

相关文章:

  • 扬帆优配|昔日白马股濒临退市,却6天5涨停!ST股突然集体爆发
  • Git 基础(一)—— Git 的安装及其配置
  • 什么是信息安全风险评估?企业如何做?
  • HBase---idea操作Hbase数据库并且映射到Hive
  • 剑指 Offer 61 扑克牌中的顺子
  • Spring 响应式编程-读书笔记
  • CI流水线的理解
  • OpenStack手动分布式部署Nova【Queens版】
  • centos7 oracle19c安装 ORA-01012: not logged on
  • 山东小巨人申报条件
  • 手写中实现并学习ahooks——useRequest
  • [手写OS]动手实现一个OS 之 准备工作以及引导扇区
  • JVM实战OutOfMemoryError异常
  • C++虚函数操作指南
  • Mybatis-Plus分页插件
  • Selenium Webdriver options的实用参数设置
  • 代码随想录算法训练营第七天|454.四数相加II 、 383. 赎金信 、 15. 三数之和 、18. 四数之和
  • 详解抓包原理以及抓包工具whistle的用法
  • 【C++】反向迭代器
  • (蓝桥真题)扫描游戏(计算几何+线段树二分)
  • 面试官:什么是双亲委派模型?如何打破它?
  • 自建服务器系列- DDNS配置
  • vue中使用axios简单封装用法,axios报错the request was rejected because no multipart boundar
  • Leetcode.1220 统计元音字母序列的数目
  • 深入元空间
  • 前端技术和框架
  • 02从零开始学Java之Java到底是个啥?
  • KEIL5中头文件路劲包含问题
  • 机智云目前我用过最便捷的物联网快速开发方案
  • MySQL基础篇1