mysql 索引 原理_MySQL——索引实现原理

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

MyISAM索引实现

MyISAM引擎使用B+Tree作为索引结构。

MyISAM会按照数据插入的顺序分配行号,从0开始,然后按照数据插入的顺序存储在磁盘上。因为行是定长的,所以可以从表的开头跳过相应的字节找到需要的行。

4ecb652462ebfae9ee1b2e97fc3277d8.png

MyISAM的一级索引(主键索引),一个节点包含多个内部节点,索引中的每个叶子节点包含“行号”。假设我们以col1为主键,则下图是一个MyISAM表的主索引(Primary key)示意。

56ab636f26ce42ff2f0e6255248fc255.png

可以看出MyISAM的索引文件仅仅保存数据记录的行号,然后通过此行号回表查询需要的数据。

那col2列上的索引(辅助索引)又会怎么样呢?有什么特别之处吗?答案是否定的,和一级索引(主键索引)没有什么区别。在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。如果我们在col2上建立一个辅助索引,则此索引的结构如下图所示:

26687d61e5222a51236711c7168b834e.png

因此,MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。MyISAM的索引方式索引和数据存放是分开的,非聚集”的,所以也叫做非聚集索引。

InnoDB索引实现

虽然InnoDB也使用B+Tree作为索引结构,但具体实现方式却与MyISAM截然不同。因为InnoDB支持聚簇索引(主键索引),聚簇索引就是表,所以InnoDB不用像MyISAM那样需要独立的行存储。也就是说,InnoDB的数据文件本身就是索引文件。

聚簇索引的每一个叶子节点都包含了主键值、事务ID、用于事务和MVCC的回滚指针以及所有的剩余列。假设我们以col1为主键,则下图是一个InnoDB表的聚簇索引(主键索引)(Primary key)示意。

e1bac3ac9f93a45f2e2c0f4ad581360d.png

与MyISAM不同的是,InnoDB的二级索引和聚簇索引很不相同。InnoDB的二级索引的叶子节点存储的不是行号(行指针),而是主键列。这种策略的缺点是二级索引需要两次索引查找,第一次在二级索引中查找主键,第二次在聚簇索引中通过主键查找需要的数据行。

画外音:可以通过我们前面提到过的索引覆盖来避免回表查询,这样就只需要一次回表查询,对于InnoDB而言,就是只需要一次索引查找就可以查询到需要的数据记录,因为需要的数据记录已经被索引到二级索引中,直接就可以找到。

好处是InnoDB在移动行时无需更新一级索引中的这个”指针“,因为主键是不会改变的,但是行指针却会改变。

InnoDB的二级索引示意如图:

cdd0dcbd723c74c642c6db9dab7033ad.png

使用InnoDB主键应该知道的事项

因为InnoDB的索引的方式通过主键聚集数据,严重依赖主键。索引如果没有定义主键,那么InnoDB会选择一个唯一的非空索引代替。如果没有这样的索引,InnoDB会隐式定义一个主键来作为聚簇索引。

聚簇索引的优点有:

1.可以把相关数据存储在一起,减少数据查询时的磁盘I/O

2.数据访问更快,因为聚簇索引就是表,索引和数据保存在一个B+Tree中

3.使用索引覆盖的查询时可以直接使用页节点中的主键值

聚簇索引的缺点有:

1.插入速度严重依赖插入顺序

2.更新聚簇索引列的代价很高,因为会强制InnoDB把更新的列移动到新的位置

3.基于聚簇索引的表在插入新行,或者主键被更新导致需要移动行的时候,可能会导致“页分裂”。当行的主键值要求必须将这一行插入到已满的页中时,存储引擎会将该页分裂为两个页面来容纳该行,这就是一次页分裂操作,页分裂会导致表占用更多的存储空间。

画外音:关于页,我们在上一篇文章中也提到过。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页。存和磁盘以页为单位交换数据。数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次磁盘I/O就可以完全载入。

基于聚簇索引以上的这些特点,在InnoDB中,我们应该尽量使用和应用无关的主键,例如自增主键,这样可以保证数据行是按照顺序写入的。而不是使用GUID、UUID生成随机的主键。

向聚簇索引中插入顺序的索引值:

每条新纪录总是在前一条记录的后面插入:

4c38c3925d3bb8e0bf50978c1c019e98.png

当页被插满后,继续插入到新的页:

16c3bf343998dc0aed9f22aff402a4d3.png

向聚簇索引中插入随机的索引值:

新的记录可能被插入到之前记录的中间,导致需要强制移动之前的记录:

769edab892951df373ba2d59cc62be0a.png

被写满且已经刷到磁盘上的页可能会被重新读取用于再次插入,此时还需要进行页分裂:

e302d85ff3d5864658200d66bf3f500c.png

总结

MyISAM和InnoDB两个存储引擎的索引虽然都是使用的B+Tree数据结构,但是在具体实现上还是存在不小差别的。InnoDB支持聚簇索引,聚簇索引就是表,所以InnoDB不用像MyISAM那样需要独立的行存储。也就是说,InnoDB的数据文件本身就是索引文件。而MyISAM的数据文件和索引文件是分开存储的。可以通过MyISAM和InnoDB如何存放表的抽象图帮助快速理解。

InnoDB(聚簇)表分布:

224a83caa9d075d038711e522a445531.png

MyISAM(非聚簇)表分布:

cca9f20bb7e82253602eea893e0d350b.png

参考

推荐阅读

c65f9d8d3992d68082615d07b0883ccb.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/244179.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql 字段 中文_如何配置mysql支持中文字段名与中文字段

匿名用户1级2018-11-18 回答中文字段名都可以了 但是中文记录不行 奇怪啊mysql>; create table a (a char(20));Query OK, 0 rows affected (0.05 sec)mysql>; insert into a values(^_^);Query OK, 1 row affected (0.05 sec)mysql>; insert into a values(中guo);Qu…

mysql中如何删除多个表格_mysql怎么批量删除多个表?

mysql批量删除多个表的方法:使用“DROP TABLE”语句,只要将表名依次写在后面,相互之间用逗号隔开即可;语法格式“DROP TABLE [IF EXISTS] 表名1 [ ,表名2, 表名3 ...]”。mysql批量删除多个表使用 DROP TABLE 语句可以删除一个或多…

mysql 图片 格式_mysql存储图片 用什么格式

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里云数据库专家保驾护航,为用户…

mysql5.5更改端口后初始化_centos7 修改mysql5.7默认端口后启动异常

关闭selinux的方法有两种:临时关闭和永久关闭。查看selinux的状态:sestatus[root162-219-29-3 ~]# sestatusSELinux status: enabledSELinuxfs mount: /sys/fs/selinuxSELinux root directory: /etc/selinuxLoaded policy name: targetedCurrent mode: e…

开启mysql日志记录_Mysql开启日志记录

vim /etc/my.conf.d/server.cnf:#lower_case_tables_name 1#错误日志log_error /var/log/mysql_error.log#慢查询日志slow_query_logONslow_query_log_file/mnt/lnx_log/mysql/slow.loglong_query_time1 #单位秒,超过此值则记录为慢查询#通用查询日志,…

mysql存储引擎innodb_MySQL常用存储引擎之Innodb

1. mysql 5.5及之后版本默认存储引擎为不了解存储引擎的数据库使用者,提供了很大的便利,因为innodb适应大部分应用场景。和myisam不同的是,innodb是一种事务型存储引擎。也就是说,innodb是支持事务的acid特性的。innodb的设计&…

mysql 的驱动是多少_mysql驱动参数变化

在java平台使用的mysql jdbc驱动为:mysql-connector-java。在项目中添加如下依赖:mysqlmysql-connector-java${version.mysql.connector}在6.0.2版本之前drivercom.mysql.jdbc.Driverurljdbc:mysql://host:port/dbname?characterEncodingutf8在6.0.2版本…

mysql 对已有表分区_mysql怎么对先有表进行分区

mysql如何对先有表进行分区?有一张表,已经创建了,是一张普通的表,先要对这张表进行hash分区,我用一下语句创建提示错误:mysql> alter table 33-> partition by hash(id)-> partitions 2;ERROR 106…

如何查看mysql my.ini_MySQL学习笔记(一)

MySQL 学习笔记一.安装Typical:经典安装Custom:自定义安装Complete: 完全安装二.修改编码方式[mysqld]myini:character-set-serverutf8[client] port3306 default-character-setutf8三.启动停止mysql服务cmd net stop mysqlcmd net start mysql四.MySQL登录mysql -V 查看版本&…

springboot quartz 动态配置_springboot集成quartz实现动态任务调度

quartz是一个开源的作业调度框架,本文就是介绍下springboot框架下继承quartz的一些使用示例首先我们需要添加quartz的spring-boot-starter-quartz依赖org.springframework.bootspring-boot-starter-quartz我们需要做一些配置。quartz提供了基于内存(MEMORY)和基于jd…

sql server cdc 清理_基于CDC技术的ElasticSearch索引同步机制

概述ElasticSearch作为一个基于Lucene的搜索引擎被广泛应用于各种应用系统,比如电商、新闻类、咨询类网站。在使用ElasticSearch开发应用的过程中,一个非常重要的过程是将数据导入到ElasticSearch索引中建立文档。在一开始系统规模比较小时,我…

mysql 8.0数据备份恢复_MySQL 8.0 增强逻辑备份恢复工具介绍-爱可生

作者:杨涛涛资深数据库专家,专研 MySQL 十余年。擅长 MySQL、PostgreSQL、MongoDB 等开源数据库相关的备份恢复、SQL 调优、监控运维、高可用架构设计等。目前任职于爱可生,为各大运营商及银行金融企业提供 MySQL 相关技术支持、MySQL 相关课…

android 字体竖直居中_问下弹性盒内不知道高度的时候想让字体垂直居中代码要怎么写...

[Asm] 纯文本查看 复制代码自适应圣杯布局* {margin: 0;padding: 0;}body,html {height: 100%;}body {display: flex;flex-direction: column;}.header {width: 100%;flex: 1;background-color: #dcdcdc;}.main {width: 100%;flex: 6;display: flex;}.left-container {flex: 1;…

mysql数据库优化清理_mysql 数据库优化整理

内连接 -- inner join内连接在不加on的情况下, 也是去求笛卡尔乘积. 不加on的用法并不推荐使用, 容易造成内存溢出的情况. 加on的时候, 在连表的时候, 就会对数据进行筛选, 以此来缩减有效数据范围。select * from A inner join B; select * from A,B; //交叉连接 -- 笛卡尔乘…

python38怎么用_Python基础练习实例38(数组操作)

题目:有一个已经排好序的数组。现输入一个数,要求按原来的从小到大顺序将它插入数组中。程序分析:首先判断此数是否大于最后一个数,然后再考虑插入中间的数的情况,插入后此元素之后的数,依次后移一个位置。…

python判断正数和负数教案_正数和负数 教学设计

《正数和负数 教学设计》由会员分享,可在线阅读,更多相关《正数和负数 教学设计(3页珍藏版)》请在人人文库网上搜索。1、1.1 正数与负数第一课时(一)概述课名是正数与负数,是义务教育课程标准实验教科书初中七年级的一堂数学课。本节课所需课…

修改pytho2安装插件的位置_office2016自定义安装以及修改安装位置

一、下载office2016专业增强版ed2k://|file|cn_office_professional_plus_2016_x86_x64_dvd_6969182.iso|2588266496|27EEA4FE4BB13CD0ECCDFC24167F9E01|/复制使用迅雷下载二、office2016部署工具部署工具地址​www.microsoft.com运行部署工具会生成setup.execonfiguration-Off…

vue 获取元素在浏览器的位置_前端开发JS获取页面元素的位置

1.网页的大小和浏览器窗口的大小一张网页的全部面积,就是它的大小。通常情况下,网页的大小由内容和document元素的clientHeight和clientWidth属性,就代表了网页的大小。function getViewport(){if (document.compatMode “BackCompat”){ret…

python 发送邮件不显示附件_python3发送邮件(无附件)

python3发送邮件代码:import smtplibfrom email.mime.text import MIMETextfrom email.utils import formatdate#设置服务器所需信息#163邮箱服务器地址mail_host smtp.163.com#163用户名mail_user h*****163.com#密码mail_pass h****password#邮件发送方邮箱地址…

小说是读者的艺术

小说的处境到了今天这个份上,该让我们的编辑和作家有点悔悟了,那就是光靠玩技巧和语言以及所有的花活唬不了读者,更救不了小说本身。我们知道一种艺术形式的存在很大程度上依赖于它的接受者的存在,所谓皮之不在,毛将存…