一文搞懂MySQL索引(实现原理加优化实战,面试必问)

史上最全的Mysql索引教程 索引是数据库中用来提高数据检索效率的数据结构。它类似于书籍的目录,可以帮助用户快速找到所需的数据,而不必扫描整个数据集。在数据库系统中,索引可以显著提高查询性能。所谓的存储引擎,说白了就是如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方法。MSQL存储引擎有 MyISAM、InnoDB、Memory,其中 InnoDB 是在 MySQL 5.5 之后成为默认的存储引擎。以下是简化版的mysql的结构图,其中,索引和数据是存储在存储引擎中的。 阅读详情

前言

本篇文章从数据结构,B+Tree的构建过程,MySQL索引实现,索引为什么那么快,MySQL有哪些索引,聚集索引和二级索引的区别,索引失效的原因,EXPLAIN关键字分析,索引实战,索引的优缺点,什么时候应该加索引,全方面帮助读者理解MySQL索引。

一、提出问题

  1. MySQL索引有哪些实现方式
  2. 什么是B+Tree索引,B+Tree索引的构建过程,跟二叉树、红黑树的对比
  3. 为什么数据库存储用B+tree索引,局部性原理是什么,为什么推荐自增id
  4. MySQL有哪些索引,聚集索引,二级索引,覆盖索引区别,回表是什么
  5. 怎么加索引,索引的使用场景有哪些,加索引一定好吗
  6. 索引失效的场景,引发什么后果
  7. EXPLAIN关键字查看MySQL是否使用索引
  8. 慢查询优化

接下来会循序渐进,让读者完全搞懂索引是什么

二、MySQL索引有哪些实现方式

MySQL索引实现方式有:B+tree索引、Hash索引、Full-text索引。

我们最常用的是B+tree索引,主键索引(也叫聚簇索引)本身就是一个B+tree索引树,非叶子节点存储主键id,叶子节点为一整行数据,叶子节点之间通过双向链表连接支持范围扫描,一般加的唯一索引,普通索引都是B+tree索引。

Hash索引只能在memory存储引擎下使用,这里不过多描述,优点是查询快,hash取模O(1)检索,缺点不支持范围查询,出现hash冲突性能会降低。

Full-text索引主要对varchar,text加索引,使用倒排索引的方式,与搜索引擎实现方式相似。

三、为什么使用B+tree索引

先说结论,主要因为磁盘读写速度远远低于内存速度,传统的机械硬盘大概慢一万倍,固态硬盘慢100倍,故减少磁盘I/O次数是提升索引性能的重点。

根据局部性原理和磁盘预读,Linux操作系统进行磁盘I/O时,一般顺序读写4KB到内存的Page Cache中,之后再在内存中找到对应的数据返回回去,Mysql的B+tree每个节点为16KB,我们可以把16kb当作磁盘IO的最小单元。

局部性原理表现为:时间局部性和空间局部性。时间局部性是指如果程序中的某条指令一旦执行,则不久之后该指令可能再次被执行;如果某数据被访问,则不久之后该数据可能再次被访问。空间局部性是指一旦程序访问了某个存储单元,则不久之后,其附近的存储单元也将被访问。

那么为什么选择B+tree作为索引呢,B+tree降低了磁盘IO次数吗?为什么不用红黑树或者hash索引呢。

关于B+tree的构建过程和红黑树的构建过程我之前写过一篇文章数据结构与算法,在后半段详细描述了二叉树,AVL树,B+tree的构建过程,这里有模拟数据结构构建过程的网站

红黑树每个节点容纳1个key,树的高度为O(log➋ N),查询复杂度也是O(log➋ N),1000000条数据,树的高度为1000,最差需要扫描1000次才能查询到对应数据。

B+tree每个节点容纳M个key,树的高度为O(logm N),m越大,树高度越低,按照mysql一个page节点存储16kb来算,一个bigint主键是8个字节,一个节点可以容纳大概1000个主键(每个节点还存储了其他隐藏信息帮助节点内部检索),m就是1000,一千万条数据,树的高度大概是3层,只需要3次磁盘I/O加上几百次内存遍历查找,就可以快速定位到数据,这对查询性能的提升的巨大的,如果没有索引而进行全表扫描的话,大概需要上万次磁盘I/O。

故基于局部性原理和磁盘预读,B+tree适合在磁盘文件系统中做检索,红黑树更适合在内存中检索(比如java的hashmap,网络epoll的连接节点存储)。

为什么推荐使用自增ID作为主键呢,B+tree的构建过程是通过分裂和合并保持树的稳定的,如上图,若不是顺序插入的,树会进行频繁的分裂,导致额外的磁盘IO和CPU使用,可以使用此网站数据结构构建过程手动测试下。

另外mysql的除主键外的普通索引的叶子节点都是id,故id越小普通索引的占用磁盘空间越小,故推荐使用int或bigint来做主键(下文详细讲)。

三、Mysql索引有哪些类型

聚集索引,非聚集索引,唯一索引,普通索引,联合索引,覆盖索引

1. 聚集索引

聚集索引,也叫主键索引,简单来说,mysql一张表的所有数据就是一个主键索引,索引的非叶子节点存储主键key,叶子节点存储具体的一行数据,当我们通过id查询数据时就通过此索引检索,若表没有设置主键,mysql会用一个隐藏字段row_id设置为主键索引。

2. 非聚集索引

非聚集索引,也叫辅助索引,二级索引,是指除主键索引外的其他索引,比如我们给一张表加一个索引。

ALTER TABLE `user` 
ADD INDEX `idx_name`(`name` ASC) USING BTREE;
复制代码

二级索引的key为我们加的字段,比如name,叶子节点是主键id。

当我们通过二级索引检索数据时,先通过二级索引检索到主键id,再拿着主键id到主键索引中查询到我们想要的数据,这个过程叫做回表

与回表对应的是覆盖索引,即当我们在二级索引树上即查询到我们要的所有数据时,就不需要再回表到主键索引查询数据,这个过程叫覆盖索引,当我们使用EXPLAIN关键字查看执行计划里有Using index就意味着我们使用了覆盖索引。

唯一索引就是有唯一约束,当表字段有两个相同的值插入时会报错。

联合索引就是对多个字段一起加索引,需要注意的是索引字段的顺序,因为联合索引的构建过程本质是先根据第一个字段进行比较排序,再根据第二个字段比较排序,以此类推。。。如果我们直接使用第二个字段查询数据,是无法使用该联合索引的,这就是最左前缀匹配原则。

若where b=1 and c=2 and a =3, 加联合索引(a,b,c)一样可以使用联合索引,mysql索引优化器会自动调整顺序,只要a=3在查询条件即可。

一般我们加联合索引是因为大部分场景都是使用这几个字段进行检索,加一个联合索引可以节省表空间,但必须保证第一个字段一定会使用检索,不然索引就失效了。

四、怎么加索引、加索引一定好吗

一般我们使用navicat可视化界面增加索引,对于varchar字段可以指定索引的键长度,减少索引的key大小,也可以指定索引的正序倒序,或选择多个字段建立索引(即联合索引)

ALTER TABLE `changlf`.`user_test_time` 
ADD INDEX `idx_username`(`username`(20) ASC) USING BTREE;
复制代码

那什么场景需要我们加索引呢?加索引有什么缺点呢?

当我们写一个sql时,where后的条件,join on后面的条件,order by排序字段,group by分组字段,在可以检索的地方,都会使用索引,select,update,delete语句在查询条件下都会使用索引,那我们这些都加索引吗?

我们知道,二级索引的key是索引字段,value是主键id,是直接存储在磁盘里的,当我们加太多的索引,会导致表空间增大,增删改的时候需要重建索引降低效率,所以我们一张表一般加3-5个索引比较合适。

哪些字段适合加索引

首先我们加索引肯定是为了检索,平常查询字段常用的字段才会加索引,但是加索引也要注意效率,需要查看索引的区分度。

索引的区分度等于count(distinct 具体的列) / count( * ),表示字段不重复的比例

区分度越大,索引检索的效率越高,唯一索引的区分度是1,而像一些状态字段,性别年龄字段,区分度很低就不适合加索引,大部分都是相同的数据,树比较大小几乎使用不到。

五、索引失效的场景、EXPLAIN关键字查看执行计划

  • 索引的失效场景:
  1. 联合索引不满足最左前缀原则,刚刚说到必须使用第一个字段进行检索。
  2. 对索引字段进行函数计算,如使用concat(),date_format()函数对索引进行修改,索引会失效,一般我们要将查询条件进行格式化使其匹配索引,而不是对索引字段进行修改。
  3. like '%a%',左%会导致范围检索,like 'a%'索引可以正常使用。
  4. in, or, between and,这些范围检索函数可能会导致索引失效,mysql有索引优化器,当我们检索的数据比较少时,比如十几条,还是会使用索引,当检索到的数据量很大时,mysql认为直接查询主键索引效率更高时,就会放弃使用二级索引。
  5. !=, not in, not null,所有取反的检索条件会导致索引失效
  • EXPLAIN关键字查看执行计划

这里有一篇文章对EXPLAIN关键字使用讲解的很详细,就不过多讲解了。

大概使用就是在sql前面加上EXPLAIN,就可以查询执行时具体会使用哪些索引了。

六、总结

本文对MySQL索引从构建原理,到各类索引实现,性能调优,优缺点进行全方面讲解,希望对读者了解索引有个清晰的认识

大厂面试快问快答,10分钟搞定MySQL夺命20问,你都能接住吗? 号外号外!《死磕 Java 并发编程》系列连载中,大家可以关注一波: 「死磕 Java 并发编程05」阿里面试失败后,一气之下我图解了Java中18把锁 「死磕 Java 并发编程04」说说Java Atomic 原子类的实现原理 「死磕 Java 并发编程03」阿里二面,面试官:说说 Java CAS 原理? 「死磕 Java 并发编程02」面试官:说说什么是 Java 内存模型(JMM)? 「死磕 Java 并发编程01」10张图告诉你Java并发多线程那些破事 先看下目录: 1说说. 阅读详情

相关推荐

阿里面试:1000万级大表, 如何 加索引?

在执行需要重建表结构的DDL操作时,如添加索引或修改列类型等,InnoDB会创建一个row_log_t对象来记录这些变更。这个对象会用于缓存DML操作日志,直到DDL操作完成。只要按照上面的 尼恩团队梳理的 方案去作答, 你的答案不是 100分,而是 120分。面试官一定是 心满意足, 五体投地。按照尼恩的梳理,进行 深度回答,可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提”。在面试之前,建议大家系统化的刷一波 5000页《

架构师尼恩 2468

MySql之索引实现

在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,本文主要讨论MyISAM和InnoDB两个存储引擎的索引实现方式。

weixin_51089557的博客 971

Xilinx XDMA驱动代码分析及用法

Xilinx XDMA驱动代码分析及用法 先简单的介绍一下,赛灵思的XDMA的驱动是用于做什么的、他的主要功能就类似与网卡pcie接口的网卡驱动、用于控制主机与fpga设备进行pcie的通讯。通讯的主要方式是设备文件的读写,这里不清楚的同学可以看一下我上一篇文章。通过控制设备文件的读写,操作驱动与fpga设备进行数据传输。 1、目录结构 zacha@Superman:~/nfs/xdma-debug/dma_ip_drivers-master/XDMA/linux-kernel$ tree -C . ├──

恍恍惚惚的大穷猫的博客 3万+

MySQL数据库之索引

目录 一、索引的概念 二、索引的作用 三、索引的副作用 四、创建索引的规则 1、适合创建为索引的字段的规则 2、MySQL的优化哪些字段/场景适合创建索引,哪些不适合 五、索引的分类和创建 1、索引的分类 2、三种创建方式 3、索引的创建演示 1、创建普通索引 (1)直接创建索引 (2)通过修改表结构创建索引 (3)通过创建表的方法创建普通索引 2、唯一索引 (1)直接创建唯一索引 (2)创建表的时候创建唯一索引 (3)通过修改表结构创建唯一索引 3、主键索引

chenzhivhao的博客 4733

基于STM32F4XX 、HAL库的GXHT30C温湿度传感器驱动应用C语言程序设计

define GXHT30C_STATUS_WRITE_CHK (1 << 0) // 写数据校验状态。#define GXHT30C_STATUS_HUMI_TRACK (1 << 11) // 湿度跟踪报警。#define GXHT30C_STATUS_TEMP_TRACK (1 << 10) // 温度跟踪报警。#define GXHT30C_STATUS_CMD_STATUS (1 << 1) // 命令执行状态。

PP_Cottage的博客 227

Node-RED系列(二二):使用dashboard搭配echarts制作漂亮的面板

在node-red中dashboard 是一个很常用的模块,其中它有一个chart节点可以用来制作一些图表,比如柱状图,折线图,饼图,但其中的图表并不是很美观,而且可配置项非常的少。 于是就有很多小伙伴找我做一套比较好看的图表面板,在对比了一下几个图表库,我选中了echarts。 不仅美观大方,而且非常容易集成,配置。下面先来看一下我做的效果。这里是直接做了四个折线图,第一个折线图有动态效果,第二个折线图是一个多线条的折线图,第三个折线图是在一个图例显示两个折线图。第二第三都可以用于数据对比。 第四个折线

知无涯 1万+

MySQL索引一篇带你彻底搞懂(一次讲清实现原理加优化实战,面试必问)

本文对MySQL索引从构建原理,到各类索引实现,性能调优,优缺点进行全方面讲解,希望对读者了解索引有个清晰的认识。

wdj_yyds的博客 289

Linux Kernel入门到精通系列讲解(RV-Kernel 篇) 5.3 从零移植 busybox,基于RISC-V

上一章节我们已经成功启动了`Ubuntu`,但是由于`Ubuntu`占用系统空间过大,所以我转向占用较小的`busybox`,预计就占用`30M`左右。开始移植busybox,基于riscv64

DSMGUOGUO的博客 856

MYSQL索引的底层实现原理

1 索引的本质 索引(Index)是帮助MySQL高效获取数据的数据结构,为什么需要需要特定的数据结构呢?首先,顺序查找这种复杂度为O(n)的算法在数据量很大时显然是糟糕的,更优秀的查找算法,比如二分查找(binary search)、二叉树查找(binary tree search),我们会发现每种查找算法都只能应用于特定的数据结构之上,但是数据本身的组织结构不可能完全满足各种数据结构,所以,在...

孟庆云的博客 5375

YOLO11改进 - 卷积Conv | StripBlockStripBlock大条带卷积块,通过顺序条带卷积捕获方向性长程依赖,强化高长宽比目标特征提取 | AAAI 2026

本文介绍了面向高纵横比目标检测的条带卷积模块——StripBlock,适用于遥感、船只、车道等细长结构目标的特征增强。该方法先通过 `5×5` 深度卷积提取局部空间信息,再利用 `1×19` 与 `19×1` 的正交长条卷积分别建模横向和纵向长程依赖,最后通过 `1×1` 卷积生成空间注意力权重,并以逐元素门控方式重标定输入特征。我们将 StripBlock 成功集成进 YOLO11,在检测头的多尺度特征层中引入条带式空间建模能力,从而增强模型对细长目标和复杂遥感场景的定位与识别效果。

魔改工程师的博客 234

论文阅读:Universal and Transferable Adversarial Attacks on Aligned Language Models. LLM Attacks

因为“即开即用”的大型语言模型能够生成大量令人反感的内容,近期的工作集中在对这些模型进行对齐,以防止不受欢迎的生成。尽管在规避这些措施方面取得了一些成功——即所谓的针对大型语言模型(LLMs)的“越狱”——这些攻击需要大量的人类智慧,并且在实践中很脆弱。自动对抗性提示生成的尝试也取得了有限的成功。在本文中,我们提出了一种简单有效的攻击方法,可以导致对齐的语言模型生成令人反感的行为。

CSPhD-winston的博客 1418

精品MySQL面试题,备战八月99%必问!过不了面试算我的

更新时, 这个情况就比较复杂了. 普通索引将记录放到 change buffer 中语句就执行完毕了. 而对唯一索引而言, 它必须要校验唯一性, 因此, 必须将数据页读入内存确定没有冲突, 然后才能继续操作. 对于写多读少的情况, 普通索引利用 change buffer 有效减少了对磁盘的访问次数, 因此普通索引性能要高于唯一索引。

Elegance never goes out of fashion 3万+

【GameFramework框架内置模块】8、文件系统(File System)

最近好忙,鸽了好久。不能颓废了,继续发力。今天分享的是GF框架的文件系统。首先,引用比较官方的说法:GF的FileSystem虚拟文件系统,使用类似磁盘存储的感念对零散的文件进行集中管理,优化资源加载时产生的内存分配,也可以对资源进行局部片段加载,极大的提升了资源加载的性能。通俗点讲就是,我这个模块就是加载磁盘文件的,优化加载时产生的内存分配。那么,它是怎么优化的呢?

优快云博客专家,Unity3D高级软件工程师,《Unity 3D从入门到实战》作者。 2452

面试必问的 MySQL,你懂了吗?

BATJTMD 面试必问的 MySQL,你懂了吗?

程序员囧辉 6万+

Unreal5从入门到精通之一文搞懂Unreal的C++代码编译之谜

我们在开发Unreal项目时,如果时蓝图模板的项目,一般问题不大,因为当你修改完蓝图,点击编译Compile+保存Save,就可以继续开发了。这对于开发者来说也非常友好。但是,如果你使用的C++模板开发项目,代码编译一切都变得魔幻起来,IDE(VS/Rider)里面有编译,编辑器里面也有编译,有什么区别呢?我们来列举几个新手常碰到的问题。1.代码我明明新建了,编辑器里怎么看不到?2.昨天我新家的功能运行的好好的,今天怎么感觉还是老逻辑。或者昨天加的新代码,新蓝图不见了。

TxNet 1606

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

一文搞懂 MySQL 中的索引

1. 什么是索引 MySQL 官方对索引的定义为:索引(Index)是帮助 MySQL 高效获取数据的数据结构。可以得到索引的本质:索引是数据结构。 举一个例子,平时看任何一本书,首先看到的都是目录,通过目录去查询书籍里面的内容会非常的迅速,如下: 书籍的目录是按顺序放置的,有第一章,第二章…,它本身就是一种顺序存放的数据结构,是一种顺序结构。 但是如果我们要去图书馆找一本书怎么办?最好的方式就是有如下的的指引: 从上面可见,整个索引结构是一棵倒挂着的树,其实它就是一种数据结构,这种数据结构比前面讲到的

个人站点:javatv.net 8906

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

面试官:MySQL索引底层数据结构原理与性能调优,你能回答多少?

面试官:听说你精通MySQL,那来和我大战三百个回合吧!

真正的大师永远怀着一颗学徒的心 1万+

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

MySQL索引优化

目录 一、MySQL索引基础 本文主要讨论MySQL索引的部分知识。将会从MySQL索引基础、索引优化实战和数据库索引背后的数据结构三部分相关内容。 一、MySQL索引基础 首先,我们将从索引基础开始介绍一下什么是索引,分析索引的几种类型,并探讨一下如何创建索引以及索引设计的基本原则。 此部分用于测试索引创建的user表的结构如下: desc user; 1. 什么是索引? "索引(在MySQL中也叫“键key”)是存储引擎快速找到记录的一种数据结构。" ——《高性能M..

给自己一个smile 6150

Mysql的常见面试题 + 索引原理分析

今天给大家分享一篇干货,面试必备之Mysql索引底层原理分析 Mysql索引的本质 Mysql索引的底层原理 Mysql索引的实战经验 面试 问:数据库中最常见的慢查询优化方式是什么? 同学A:加索引。 问:为什么加索引能优化慢查询? 同学A:...不知道 同学B:因为索引其实就是一种优化查询的数据结构,比如Mysql中的索引是用B+树实现的,而B...

勇往直前的专栏 2万+

【MySQL】一文搞懂MySQL索引所有知识点

MySQL索引是优化数据库查询和提升查询性能的利器。在日常开发中,合理使用索引不仅能显著提升数据库操作的速度,还能减少系统资源的消耗。本文将详细讲解MySQL索引的基础概念、类型、工作原理及优化建议,帮助你全面理解和灵活运用MySQL索引。

科技改变人类,技术成就未来 5281

MySQL 索引一篇讲透:原理、分类、优化与面试总结

但很多时候,我们只是记住了“B+树比哈希更适合范围查询”、“联合索引要满足最左匹配”、“覆盖索引可以减少回表”,却并没有真正理解这些结论背后的原因。 这篇文章就从面试高频问题出发,把 MySQL 索引的原理、分类、底层结构、查询过程、失效场景和优化方法系统整理一遍,帮助自己把这块知识真正吃透。

2302_80067378的博客 5922

一文搞懂MySQL索引数据结构

前言 当我们在查询数据慢的情况下第一个想到的会是添加索引,索引在数据库的实际应用场景中十分常见,数据库的优化也离不开对索引的优化。而且索引相关的知识也是面试频率非常高的点之一,因此,本文将从基础理论出发,介绍MySQL按照逻辑角度的索引分类和实现。通过索引数据结构的实现原理阐述不同结构对建立索引带来的优劣势,希望通过这篇文章能给大家带来收获。 SQL执行慢的原因分析 磁盘空间不足、内存不足、I/O吞吐量小或者网络差等原因。 表没有创建索引或者索引已经失效。 分库分表也会带来SQL慢的原因 服务器调优及各.

养歌的博客 5900

MySQL索引优化指南:如何科学地为数据表添加索引

MySQL索引优化指南 索引是提升数据库查询性能的关键工具。本文系统介绍了索引的使用场景与优化策略: 何时加索引 高频查询条件、JOIN字段、排序分组列 高选择性列(唯一值多)和大表查询 何时避免索引 小表、低选择性列(如性别) 频繁更新字段和不用于查询的列 优化方法 使用EXPLAIN分析查询执行计划 遵循最左前缀原则设计复合索引 监控慢查询日志和未使用索引 最佳实践 优先优化高频查询 避免过度索引影响写入性能 定期重建索引保持效率 通过科学评估查询模式,合理设计索引,

私聊前往站内信:https://i.youkuaiyun.com/#/msg/chat/weixin_44976692 1万+

mysql系列【你不知道的索引优化】(面试必问)

前言:相信大家面试的时候肯定被问过这个问题,但很多都是因为不够深入,或者了解片面而导致好的机会和你失之交臂,其实这个问题答得好是非常加分的,好了不多说了开始… 让索引效率更高:这其中就涉及到索引的选择性了,索引的选择性是指索引列中不同值的数目与表中记录数的比。如果一个表中有2000条记录,表索引列有1980个不同的值,那么这个索引的选择性就是1980/2000=0.99。一个索引的选择性越接近于1,这个索引的效率就越高

jar壳虫的博文 3205

【BATJ】面试必问MySQL索引实现原理

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34384915的博客 608
上一篇: 京东内网遭开源的“顶级”SpringCloud实战手册,GitHub列为首推
下一篇: 弯道超车,阿里高工新产Java面试速成指南,面试骚操作都在里面了
程序员职业指南
博客等级 码龄4年 2136粉丝 960原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值