MYSQL索引连环18问(上)

news/2025/2/4 1:07:56/

MYSQL索引连环18问(上)

1.索引是什么?

  • 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。
  • 索引是一种数据结构。数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。更通俗的说,索引就相当于目录。为了方便查找书中的内容,通过对内容建立索引形成目录。而且索引是一个文件,它是要占据物理空间的。
  • MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。比如我们在查字典的时候,前面都有检索的拼音和偏旁、笔画等,然后找到对应字典页码,这样然后就打开字典的页数就可以知道我们要搜索的某一个key的全部值的信息了。

2. 索引有哪些优缺点?

索引的优点

  • 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
  • 通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

索引的缺点

  • 时间方面:创建索引和维护索引要耗费时间,具体地,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,会降低增/改/删的执行效率;
  • 空间方面:索引需要占物理空间。

3. MySQL有哪几种索引类型?

  • 从存储结构上来划分:BTree索引(B-Tree或B+Tree索引),Hash索引,full-index全文索引,R-Tree索引。这里所描述的是索引存储时保存的形式,
  • 从应用层次来分:普通索引,唯一索引,复合索引。
    • 普通索引:即一个索引只包含单个列,一个表可以有多个单列索引
    • 唯一索引:索引列的值必须唯一,但允许有空值
    • 复合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并
    • 聚簇索引(聚集索引):并不是一种单独的索引类型,而是一种数据存储方式。具体细节取决于不同的实现,InnoDB的聚簇索引其实就是在同一个结构中保存了B-Tree索引(技术上来说是B+Tree)和数据行。
    • 非聚簇索引: 不是聚簇索引,就是非聚簇索引
  • 根据中数据的物理顺序与键值的逻辑(索引)顺序关系: 聚集索引,非聚集索引。

4. 说一说索引的底层实现?

Hash索引

基于哈希表实现,只有精确匹配索引所有列的查询才有效,对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码(hash code),并且Hash索引将所有的哈希码存储在索引中,同时在索引表中保存指向每个数据行的指针。

图片来源:https://www.javazhiyin.com/40232.html
B-Tree索引(MySQL使用B+Tree)

B-Tree能加快数据的访问速度,因为存储引擎不再需要进行全表扫描来获取数据,数据分布在各个节点之中。

在这里插入图片描述

B+Tree索引

是B-Tree的改进版本,同时也是数据库索引索引所采用的存储结构。数据都在叶子节点上,并且增加了顺序访问指针,每个叶子节点都指向相邻的叶子节点的地址。相比B-Tree来说,进行范围查找时只需要查找两个节点,进行遍历即可。而B-Tree需要获取所有节点,相比之下B+Tree效率更高。

B+tree性质:

  • n棵子tree的节点包含n个关键字,不用来保存数据而是保存数据的索引。
  • 所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
  • 所有的非终端结点可以看成是索引部分,结点中仅含其子树中的最大(或最小)关键字。
  • B+ 树中,数据对象的插入和删除仅在叶节点上进行。
  • B+树有2个头指针,一个是树的根节点,一个是最小关键码的叶节点。

在这里插入图片描述

5. 为什么索引结构默认使用B+Tree,而不是B-Tree,Hash,二叉树,红黑树?

B-tree: 从两个方面来回答

  • B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B(B-)树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。
  • 由于B+树的数据都存储在叶子结点中,分支结点均为索引,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。

Hash:

  • 虽然可以快速定位,但是没有顺序,IO复杂度高;
  • 基于Hash表实现,只有Memory存储引擎显式支持哈希索引 ;
  • 适合等值查询,如=、in()、<=>,不支持范围查询 ;
  • 因为不是按照索引值顺序存储的,就不能像B+Tree索引一样利用索引完成排序 ;
  • Hash索引在查询等值时非常快 ;
  • 因为Hash索引始终索引的所有列的全部内容,所以不支持部分索引列的匹配查找 ;
  • 如果有大量重复键值得情况下,哈希索引的效率会很低,因为存在哈希碰撞问题 。
  • 二叉树: 树的高度不均匀,不能自平衡,查找效率跟数据有关(树的高度),并且IO代价高。
  • 红黑树: 树的高度随着数据量增加而增加,IO代价高。

6. 讲一讲聚簇索引与非聚簇索引?

在 InnoDB 里,索引B+ Tree的叶子节点存储了整行数据的是主键索引,也被称之为聚簇索引,即将数据存储与索引放到了一块,找到索引也就找到了数据。

而索引B+ Tree的叶子节点存储了主键的值的是非主键索引,也被称之为非聚簇索引、二级索引。

聚簇索引与非聚簇索引的区别:

  • 非聚集索引与聚集索引的区别在于非聚集索引的叶子节点不存储表中的数据,而是存储该列对应的主键(行号)
  • 对于InnoDB来说,想要查找数据我们还需要根据主键再去聚集索引中进行查找,这个再根据聚集索引查找数据的过程,我们称为回表。第一次索引一般是顺序IO,回表的操作属于随机IO。需要回表的次数越多,即随机IO次数越多,我们就越倾向于使用全表扫描
  • 通常情况下, 主键索引(聚簇索引)查询只会查一次,而非主键索引(非聚簇索引)需要回表查询多次。当然,如果是覆盖索引的话,查一次即可
  • 注意:MyISAM无论主键索引还是二级索引都是非聚簇索引,而InnoDB的主键索引是聚簇索引,二级索引是非聚簇索引。我们自己建的索引基本都是非聚簇索引。

7. 非聚簇索引一定会回表查询吗?

不一定,这涉及到查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再进行回表查询。一个索引包含(覆盖)所有需要查询字段的值,被称之为"覆盖索引"。

举个简单的例子,假设我们在员工表的年龄上建立了索引,那么当进行select score from student where score > 90的查询时,在索引的叶子节点上,已经包含了score 信息,不会再次进行回表查询。

8. 联合索引是什么?为什么需要注意联合索引中的顺序?

MySQL可以使用多个字段同时建立一个索引,叫做联合索引。在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引。

具体原因为:

MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序。

当进行查询时,此时索引仅仅按照name严格有序,因此必须首先使用name字段进行等值查询,之后对于匹配到的列而言,其按照age字段严格有序,此时可以使用age字段用做索引查找,以此类推。因此在建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面。此外可以根据特例的查询或者表结构进行单独的调整。

9. 讲一讲MySQL的最左前缀原则?

最左前缀原则就是最左优先,在创建多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。 mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。


http://www.ppmy.cn/news/92459.html

相关文章

C++——引用

引用的概念 初步理解&#xff1a;引用相当于给变量取了一个别名&#xff0c;它和引用的变量共用同一块空间。 就好比孙悟空有很多外号&#xff0c;例如孙行者&#xff0c;齐天大圣&#xff0c;斗战胜佛&#xff0c;但是它们所指都是孙悟空。同样的&#xff0c;如果齐天大圣大…

代码随想录算法训练营15期 Day 3 | 203.移除链表元素 、707.设计链表 、206.反转链表

今日任务 链表理论基础 203.移除链表元素 707.设计链表 206.反转链表 链表理论基础 链表是一种通过指针串联在一起的线性结构&#xff0c;每一个节点由两部分组成&#xff0c;一个是数据域一个是指针域&#xff08;存放指向下一个节点的指针&#xff09;&#xff0c;最后…

五、Docker仓库之https的registry搭建(二)

本节我们分享更多的实用的仓库搭建使用方式。包括支持https的registry、Harbor、nexus。 支持HTTPS的registry 准备站点证书&#xff08;测试使用&#xff0c;用一个自己的测试域名&#xff0c;配置本地hosts&#xff09; 如果你拥有一个公网域名&#xff0c;那很好&#xff…

博客系统后端设计(五) - 实现登录页面功能

文章目录 约定前后端交互接口修改前段代码修改后端代码登录测试 约定前后端交互接口 这里约定请求是一个 POST 请求&#xff0c;路径是 /login&#xff0c;使用的是以下的格式&#xff1a; usernamzhangsan&password123 响应是 HTTP/1.1 302&#xff0c;因为在成功登录之…

promise-reflect-proxy

1-Object.defineProperty 这个方法是用来为对象新增属性或者修改对象属性并返回这个对象的。 属性描述符分为数据描述符和访问器描述符&#xff1b; 不是专门用于劫持对象属性的方法&#xff0c;想要监听属性的新增与删除也是无法做到的。 2-Proxy提供对于对象的代理 proxy类…

charles使用

charles​ 一、概念​ charles是一款非常优秀的抓包工具&#xff0c;全平台支持&#xff0c;在mac&#xff0c;windows&#xff0c;linux上都可以使用&#xff0c;既可以抓 取web端的包&#xff0c;也可以抓app端的包。 ​ charles主要的功能包括如下几点&#xff1a; ​ 截取…

Scala介绍,开发环境搭建,语法,高级特性,编程技巧

Scala是一种面向对象和函数式编程语言&#xff0c;它运行在Java虚拟机上&#xff0c;可以与Java代码无缝地集成。Scala的设计目标是将面向对象和函数式编程的最佳实践结合起来&#xff0c;以提高代码的可读性、可维护性和可扩展性。本文将介绍Scala的开发环境搭建、语法、高级特…

腾讯云CVM服务器端口怎么开通?以开80端口为例

腾讯云CVM服务器端口是通过配置安全组规则来开通的&#xff0c;阿腾云以开通80端口为例来详细说下腾讯云轻量应用服务器开启端口的方法&#xff0c;其他的端口的开通如8080、1433、443、3306、8888等端口也适用于此方法&#xff0c;腾讯云服务器开通端口教程如下&#xff1a; …