MySQL——索引实现原理
在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,本文主要讨论MyISAM和InnoDB两个存储引擎的索引实现方式。
MyISAM索引实现
MyISAM引擎使用B+Tree作为索引结构。
MyISAM会按照数据插入的顺序分配行号,从0开始,然后按照数据插入的顺序存储在磁盘上。因为行是定长的,所以可以从表的开头跳过相应的字节找到需要的行。
MyISAM的一级索引(主键索引),一个节点包含多个内部节点,索引中的每个叶子节点包含“行号”。假设我们以col1为主键,则下图是一个MyISAM表的主索引(Primary key)示意。
可以看出MyISAM的索引文件仅仅保存数据记录的行号,然后通过此行号回表查询需要的数据。
那col2列上的索引(辅助索引)又会怎么样呢?有什么特别之处吗?答案是否定的,和一级索引(主键索引)没有什么区别。在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。如果我们在col2上建立一个辅助索引,则此索引的结构如下图所示:
因此,MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。MyISAM的索引方式索引和数据存放是分开的,非聚集”的,所以也叫做非聚集索引。
InnoDB索引实现
虽然InnoDB也使用B+Tree作为索引结构,但具体实现方式却与MyISAM截然不同。因为InnoDB支持聚簇索引(主键索引),聚簇索引就是表,所以InnoDB不用像MyISAM那样需要独立的行存储。也就是说,InnoDB的数据文件本身就是索引文件。
聚簇索引的每一个叶子节点都包含了主键值、事务ID、用于事务和MVCC的回滚指针以及所有的剩余列。假设我们以col1为主键,则下图是一个InnoDB表的聚簇索引(主键索引)(Primary key)示意。
与MyISAM不同的是,InnoDB的二级索引和聚簇索引很不相同。InnoDB的二级索引的叶子节点存储的不是行号(行指针),而是主键列。这种策略的缺点是二级索引需要两次索引查找,第一次在二级索引中查找主键,第二次在聚簇索引中通过主键查找需要的数据行。
画外音:可以通过我们前面提到过的索引覆盖来避免回表查询,这样就只需要一次回表查询,对于InnoDB而言,就是只需要一次索引查找就可以查询到需要的数据记录,因为需要的数据记录已经被索引到二级索引中,直接就可以找到。
好处是InnoDB在移动行时无需更新一级索引中的这个”指针“,因为主键是不会改变的,但是行指针却会改变。
InnoDB的二级索引示意如图:
使用InnoDB主键应该知道的事项
因为InnoDB的索引的方式通过主键聚集数据,严重依赖主键。索引如果没有定义主键,那么InnoDB会选择一个唯一的非空索引代替。如果没有这样的索引,InnoDB会隐式定义一个主键来作为聚簇索引。
聚簇索引的优点有:
1.可以把相关数据存储在一起,减少数据查询时的磁盘I/O
2.数据访问更快,因为聚簇索引就是表,索引和数据保存在一个B+Tree中
3.使用索引覆盖的查询时可以直接使用页节点中的主键值
聚簇索引的缺点有:
1.插入速度严重依赖插入顺序
2.更新聚簇索引列的代价很高,因为会强制InnoDB把更新的列移动到新的位置
3.基于聚簇索引的表在插入新行,或者主键被更新导致需要移动行的时候,可能会导致“页分裂”。当行的主键值要求必须将这一行插入到已满的页中时,存储引擎会将该页分裂为两个页面来容纳该行,这就是一次页分裂操作,页分裂会导致表占用更多的存储空间。
画外音:关于页,我们在上一篇文章中也提到过。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页。存和磁盘以页为单位交换数据。数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次磁盘I/O就可以完全载入。
基于聚簇索引以上的这些特点,在InnoDB中,我们应该尽量使用和应用无关的主键,例如自增主键,这样可以保证数据行是按照顺序写入的。而不是使用GUID、UUID生成随机的主键。
向聚簇索引中插入顺序的索引值:
每条新纪录总是在前一条记录的后面插入:
当页被插满后,继续插入到新的页:
向聚簇索引中插入随机的索引值:
新的记录可能被插入到之前记录的中间,导致需要强制移动之前的记录:
被写满且已经刷到磁盘上的页可能会被重新读取用于再次插入,此时还需要进行页分裂:
总结
MyISAM和InnoDB两个存储引擎的索引虽然都是使用的B+Tree数据结构,但是在具体实现上还是存在不小差别的。InnoDB支持聚簇索引,聚簇索引就是表,所以InnoDB不用像MyISAM那样需要独立的行存储。也就是说,InnoDB的数据文件本身就是索引文件。而MyISAM的数据文件和索引文件是分开存储的。可以通过MyISAM和InnoDB如何存放表的抽象图帮助快速理解。
InnoDB(聚簇)表分布:
MyISAM(非聚簇)表分布:
参考
《高性能MySQL》
推荐阅读
MySQL——通过EXPLAIN分析SQL的执行计划
MySQL——索引基础
MySQL——索引优化实战
数据库索引背后的数据结构
是什么影响了数据库索引选型?
MySQL——索引实现原理的更多相关文章
- MYSQL索引结构原理、性能分析与优化
[转]MYSQL索引结构原理.性能分析与优化 第一部分:基础知识 索引 官方介绍索引是帮助MySQL高效获取数据的数据结构.笔者理解索引相当于一本书的目录,通过目录就知道要的资料在哪里, 不用一页一页 ...
- 【转】由浅入深探究mysql索引结构原理、性能分析与优化
摘要: 第一部分:基础知识 第二部分:MYISAM和INNODB索引结构 1.简单介绍B-tree B+ tree树 2.MyisAM索引结构 3.Annode索引结构 4.MyisAM索引与Inno ...
- 重新学习MySQL数据库4:Mysql索引实现原理
重新学习Mysql数据库4:Mysql索引实现原理 MySQL索引类型 (https://www.cnblogs.com/luyucheng/p/6289714.html) 一.简介 MySQL目前主 ...
- MySQL索引的原理,B+树、聚集索引和二级索引
MySQL索引的原理,B+树.聚集索引和二级索引的结构分析 一.索引类型 1.1 B树 1.2 B+树 1.3 哈希索引 1.4 聚集索引(clusterd index) 1.5 二级索引(secon ...
- mysql索引工作原理、分类
一.概述 在mysql中,索引(index)又叫键(key),它是存储引擎用于快速找到所需记录的一种数据结构.在越来越大的表中,索引是对查询性能优化最有效的手段,索引对性能影响非常关键.另外,mysq ...
- 重新学习Mysql数据库4:Mysql索引实现原理和相关数据结构算法
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
- MySQL索引结构原理分析
我们在学习MySQL的时候经常会听到索引这个词,大概也知道这是什么,但是深究下去又说不出什么道道来.下面将会比较全面的介绍一下关于索引! 1 索引是什么? 这里用百度百科的一句话来说,在关系数据库中, ...
- Mysql 索引实现原理. 聚集索引, 非聚集索引
Mysql索引实现: B-tree,B是balance,一般用于数据库的索引.使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度.而B+tree是B-tree的一个变种,My ...
- mysql 索引及其原理
mysql 索引 KEY与INDEX的区别: KEY is something on the logical level, describes your table and database desi ...
随机推荐
- (转)shlex — 解析 Shell 风格语法
原文:https://pythoncaff.com/docs/pymotw/shlex-parse-shell-style-syntaxes/171 这是一篇协同翻译的文章,你可以点击『我来翻译』按钮 ...
- github绑定自己的域名
1.进入需要绑定域名的项目里面,然后新建一个文件CNAME,没有后缀的. 2.在文件里面输入你的域名,然后保存.github这边就完成了. 3.然后去你购买域名的网站,进入控制台,找到域名,然后域名解 ...
- 面试:C++String类实现
#include <iostream> #include <cstring> using namespace std; class CString { private: cha ...
- PTA (Advanced Level) 1003 Emergency
Emergency As an emergency rescue team leader of a city, you are given a special map of your country. ...
- study design of ADNI
AD(Alzheimers disease):不可逆的神经退化,患病人员会由于脑部问题的恶化而导致心智功能不健全. ADNI:阿尔茨海默氏症神经成像项目 ADNI的总体目标是验证用于阿尔茨海默病临床 ...
- 一篇你看了就懂的DNS详解
DNS(Domain Name System,域名系统),万维网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住IP. 通过域名,最终得到该域名对应的IP地址 ...
- SpringMVC源码阅读:属性编辑器、数据绑定
1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...
- No caching ——无缓存工具
No caching ——无缓存工具 无缓存工具阻止客户端应用程序(如Web浏览器)缓存任何资源,因此,请求总是发送到远程站点,所以我们总能看到最新版本. 适用场景 开发每次新部署了一版环境,说解决了 ...
- C#使用命令编译代码
1.在路径%SystemRoot%\Microsoft.NET\Framework\vX.X.X(安装的.net版本号)下找到csc.exe,在cmd窗口cd到该路径下. ps(在该路径下有一个CSC ...
- VC++6.0调试:Watch窗口的使用
#include <stdio.h> #include <windows.h> class AutoExpand { public: AutoExpand(int val, c ...