这样理解Mysql索引,阿里面试官也给你点赞

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 索引是Mysql的一块硬骨头,但是对于程序猿来说又是十分重要的基础技能。在平常的项目开发中,它是重要的SQL优化手段。在求职面试中,它是面试官常常用来考察求职者数据库性能优化方面的重要考量。因此透彻的掌握索引原理,并能够将其运用到数据库查询实战是每个程序猿必备的能力。本文将从索引原理、索引设计原则方面阐述Mysql索引。相信阅读完本文之后,在Mysql索引查询数据理解这块完全可以征服阿里面试官。准备好了吗?我们发车了。

引言

索引是Mysql的一块硬骨头,但是对于程序猿来说又是十分重要的基础技能。在平常的项目开发中,它是重要的SQL优化手段。在求职面试中,它是面试官常常用来考察求职者数据库性能优化方面的重要考量。因此透彻的掌握索引原理,并能够将其运用到数据库查询实战是每个程序猿必备的能力。本文将从索引原理、索引设计原则方面阐述Mysql索引。相信阅读完本文之后,在Mysql索引查询数据理解这块完全可以征服阿里面试官。准备好了吗?我们发车了。


索引原理

在进行索引设计以及优化之前,我们先深入理解下索引的原理。因为所有的设计以及优化一定是建立在你对原理的透彻理解的基础上。

很多人都知道,在进行SQL查询时,同样一张表、同样的数据。不加索引以及加索引进行数据查询。两者差别很多。那么到底是为什么有这种差距。简单来说,如果把业务数据比作为一本字典的话,那么索引就是这本字典的目录。如果我让你查一个字,在你不使用目录查的时候,那只能一页一页的翻,运气不好的话可能要翻到最后一页才能查到想要的字,这就是传说中的全表扫描。但是如果我们通过目录来查找,那么可以很快定位字所在页,进而查找到对应的字。看到了吧,索引的威力就在于提高数据查询的效率。好了,现在我们对于索引有了感性的认识。那么我们接下来就深入了解下。


我们都知道在Mysql中索引的数据结构是B+树(这里不再说明B树、Hash索引等结构的优劣,不是本文的重点),那么我们就一步一步来看看,索引在磁盘中的B+树是怎么长成的。


1、数据页

在日常的项目开发中,我们的业务数据大部分都存在关系型数据中。那么数据库中各个表中的数据最终也都是存储在服务器的硬盘当中的。不知道大家有没有想过这个数据到底是怎么存储的呢?实际上Mysql数据库中我们每天都在使用的数据库表是对于人来理解的逻辑表。它实际在磁盘当中是通过一页页的数据页进行存储的。数据页是磁盘与内存交互的基本单位,Mysql的Innodb存储引擎,实际通过buffer pool与磁盘中的数据页进行交互,而不是直接操作磁盘中的数据页。数据页的结构如下图所示:

image.png

同时相邻的数据页之间通过双向链表来维护数据页之间的相互引用。如下图所示,橙红色部分即为数据页,中间的小框框可以理解为一条条具体的数据。Mysql的InnoDB存储引擎数据页大小是16KB。Mysql的Innodb存储引擎通过页号来唯一定位一个数据页,因此每个数据页都有自己的页号。通过上图可知,每个数据页都有都有对应的Page Header,在Page Header中保存了当前数据页的页号,以及其下一页的页号和上一页的页号。

image.png

相邻的数据之间通过指针进行互相引用,指针标注数据页的页号,每个数据页中存储了连续的一段数据,每个数据行中的记录头部存有下一行记录真实数据的地址偏移量,简单理解为拥有指针指向下一行数据的地址。因此在数据页的内部,实际是关于数据行的单向链表。这个单向链表是关于主键id的,从小到大进行排列。

image.png

从上述的数据页结构可知,每次进行数据插入时User Records区域就会变大,相应的的User Record区域就会减少。当User Record区域消耗完之后,就会发生页分裂,形成新的数据页。这里需要注意的是,如果我们使用的是Mysql中的自增主键,那么可以保证按照id的增长顺序进行数据行排列,但是如果主键是我们自己设置的并不是自增长的,那么有可能出现后面插入的数据的主键值小于前面数据的主键值,那么在进行页分裂的时候,Mysql会按照主键大小重新进行排列。此处不知道大家有没有疑问,为什么一定要按照主键大小进行排列呢?实际上和后续的数据查询有关系,数据页中的数据按照主键顺序进行排列是索引可以正常运行的基础。大致的过程如下图所示:

image.png

2、页目录

每个数据页都有自己的页目录上面页结构中的Page Directory,这个页目录的作用实际上就是用来进行数据行定位的。数据页中的数据实际上是按组分配的,页目录中的不同的槽位,其实是对应了数据页中的不同的分组,查询数据时,通过id找到对应的槽,再根据对应的槽来知道对应在数据页中的数据行分组,遍历数据行分组中的数据直到找到对应的数据。

image.png

3、索引原理分析

(1)索引基础

有了上面两节的数据页的基础知识之后,我们再来探讨索引原理就更加容易理解了。在没有索引时,数据查询都是进行全表扫描。遍历查询数据页中的每个数据行,再遍历所有的数据页,知道找到符合条件的数据项。因此查询效率十分的低下。那么应该怎么才能提供数据查询的效率呢?能不能像字典的目录一样,也搞个主键目录来进行数据页号的定位呢?答案是肯定的,Mysql实际也正是这么做的。Mysql通过主键目录实际就是传说中的主键索引,实现数据的查询优化。在主键目录中包含了两个重要元素,一个是数据页中最小的主键,另一个是当前数据页的页号。这样可以通过这个主键目录方面的进行数据查询。


举个栗子,如果此时想要查询主键id=5的数据,那么首先在主键目录中进行查找。此时发现主键id=5大于主键id=1,但是又小于id=8,那么就可以确定实际上数据实际是在页号为1的数据页中的。


当然在实际在Mysql中会有很多的数据页,因此对应的主键索引也会很多,那么此时就需要通过二分查找的方式进行数据页定位,再查找到对应的数据。

image.png

(2)索引页

如今当下,各个互联网公司迅猛发展,对应的业务量也是十分巨大。因此数据库中的数据量也是十分庞大的。表中的数据几百万、上千万可能很常见,按照上述的主键目录,那么就需要存储大量的主键与数据页号。即便是进行二分查找,其数据查询效率也是比较低的。

Mysql实际是将索引说句存储在索引页中的,当数据量比较大时候,对应的索引也会比较多,因此通过专门的索引页来存储索引数据。另外在这些索引页的上层又通过主键与索引页号来继续进行索引页的查询定位,因此我们得到如下的结构。其中的id号指的是对应最小的id号。

image.png

如果索引页中的数据越来越多,索引页同样会进行页分裂。这样索引页也就形成了不同的层级,索引页层、索引页、数据页这三个页数据就形成了我们说的B+树。下图就是索引的B+树结构,通过它完成数据查询效率远高于全表扫描。B+的叶子节点才会存储数据,下图是一种主键索引,也叫聚簇索引。其实我们可以看出来,它的根本思想就是分而治之的思想。数据量很大是吧,那我就把数据分成很多的数据页,数据页很多是吧,那我就通过索引页来组织数据页,索引页很多是吧,那就再通过索引页来索引。

image.png

我们再来看下,数据查询在B+树中的查询过程。举个栗子,如当前需要查询id为3的数据,那么将在索引页中判断应该走索引页为3的索引页。那么在索引页为3中继续判断id=1应该走索引页为1的索引页,在索引页中判断应该页号为1的数据页,在此数据页中遍历最终查询到对应的数据。

image.png

以上通过索引页与数据页组成的B+树就是聚簇索引,当然我们也可以通过其他字段来建立普通索引。知识普通索引会的叶子节点存储的是对应的主键id,而不是具体的数据,索引会存在回表的问题,即查询到对应的id之后,还需要根据id继续到聚簇索引中查询具体的数据,通过这样的操作才能查询到select *的所有数据。当然我们可以通过覆盖索引的方式避免这样的查询浪费。

总结

本文通过一步步图解的方式,为大家拆解MysqlInnoDB的索引原理,同时构建出对应的B+树索引结构。阐述了数据查询的具体过程。相信大家对于索引这块有了更加深刻的理解,后面会从实战的角度出发,分析下如何设计索引以及如何应对索引失效的问题。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
4天前
|
SQL 关系型数据库 MySQL
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
MySQL慢查询优化、索引优化,是必知必备,大厂面试高频,本文深入详解,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
|
25天前
|
存储 关系型数据库 MySQL
阿里面试:为什么要索引?什么是MySQL索引?底层结构是什么?
尼恩是一位资深架构师,他在自己的读者交流群中分享了关于MySQL索引的重要知识点。索引是帮助MySQL高效获取数据的数据结构,主要作用包括显著提升查询速度、降低磁盘I/O次数、优化排序与分组操作以及提升复杂查询的性能。MySQL支持多种索引类型,如主键索引、唯一索引、普通索引、全文索引和空间数据索引。索引的底层数据结构主要是B+树,它能够有效支持范围查询和顺序遍历,同时保持高效的插入、删除和查找性能。尼恩还强调了索引的优缺点,并提供了多个面试题及其解答,帮助读者在面试中脱颖而出。相关资料可在公众号【技术自由圈】获取。
|
18天前
|
SQL 缓存 关系型数据库
美团面试:Mysql 有几级缓存? 每一级缓存,具体是什么?
在40岁老架构师尼恩的读者交流群中,近期有小伙伴因未能系统梳理MySQL缓存机制而在美团面试中失利。为此,尼恩对MySQL的缓存机制进行了系统化梳理,包括一级缓存(InnoDB缓存)和二级缓存(查询缓存)。同时,他还将这些知识点整理进《尼恩Java面试宝典PDF》V175版本,帮助大家提升技术水平,顺利通过面试。更多技术资料请关注公号【技术自由圈】。
美团面试:Mysql 有几级缓存? 每一级缓存,具体是什么?
|
5天前
|
SQL 关系型数据库 MySQL
阿里面试:1000万级大表, 如何 加索引?
45岁老架构师尼恩在其读者交流群中分享了如何在生产环境中给大表加索引的方法。文章详细介绍了两种索引构建方式:在线模式(Online DDL)和离线模式(Offline DDL),并深入探讨了 MySQL 5.6.7 之前的“影子策略”和 pt-online-schema-change 方案,以及 MySQL 5.6.7 之后的内部 Online DDL 特性。通过这些方法,可以有效地减少 DDL 操作对业务的影响,确保数据的一致性和完整性。尼恩还提供了大量面试题和解决方案,帮助读者在面试中充分展示技术实力。
|
12天前
|
SQL 算法 关系型数据库
面试:什么是死锁,如何避免或解决死锁;MySQL中的死锁现象,MySQL死锁如何解决
面试:什么是死锁,死锁产生的四个必要条件,如何避免或解决死锁;数据库锁,锁分类,控制事务;MySQL中的死锁现象,MySQL死锁如何解决
|
16天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
82 1
|
19天前
|
SQL 关系型数据库 MySQL
美团面试:Mysql如何选择最优 执行计划,为什么?
在40岁老架构师尼恩的读者交流群中,近期有小伙伴面试美团时遇到了关于MySQL执行计划的面试题:“MySQL如何选择最优执行计划,为什么?”由于缺乏系统化的准备,小伙伴未能给出满意的答案,面试失败。为此,尼恩为大家系统化地梳理了MySQL执行计划的相关知识,帮助大家提升技术水平,展示“技术肌肉”,让面试官“爱到不能自已”。相关内容已收录进《尼恩Java面试宝典PDF》V175版本,供大家参考学习。
|
17天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
47 0
|
3月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
8天前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?