上一章讲了数据库基本上都用 B+ 树来存储索引的原因:适合磁盘存储,能够充分利用多叉平衡树的特性,磁盘预读,并且很好的支持等值,范围,顺序扫描等。这篇主要介绍 MySQL 两种常用引擎,MyISAM 和 InnoDB 的索引组织方式,了解这些存储方式,对数据库优化很有帮助。

MySQL 的索引按照存储方式分为两类:

聚集索引:也称 Clustered Index。是指关系表记录的物理顺序与索引的逻辑顺序相同。由于一张表只能按照一种物理顺序存放,一张表最多也只能存在一个聚集索引。与非聚集索引相比,聚集索引有着更快的检索速度。

MySQL 里只有 INNODB 表支持聚集索引,INNODB 表数据本身就是聚集索引,也就是常说 IOT,索引组织表。非叶子节点按照主键顺序存放,叶子节点存放主键以及对应的行记录。所以对 INNODB 表进行全表顺序扫描会非常快。

非聚集索引:也叫 Secondary Index。指的是非叶子节点按照索引的键值顺序存放,叶子节点存放索引键值以及对应的主键键值。MySQL 里除了 INNODB 表主键外,其他的都是二级索引。MYISAM,memory 等引擎的表索引都是非聚集索引。简单点说,就是索引与行数据分开存储。一张表可以有多个二级索引。

MYISAM 表:

MYISAM 表是典型的数据与索引分离存储,主键和二级索引没有本质区别。比如在 MYISAM 表里主键、唯一索引是一样的,没有本质区别。

假设表 t1 为 MYISAM 引擎,列为 ID,姓名,性别,年龄,手机号码。其中 ID 为主键,年龄为二级索引。记录如下:

那对应的两个 B+ 树索引如下图所示,

主键字段索引树:

上图是一个 3 阶的 B+ 树,非叶子节点按照主键的值排序存储,叶子节点同样按照主键的值排序存储,并且包含指向磁盘上的物理数据行指针。

年龄字段索引树:

上图年龄字段索引树同样是一个 3 阶的 B+ 树,非叶子节点按照年龄字段的值顺序存储,叶子节点保存年龄字段的值以及指向磁盘上的物理数据行指针。

从上面两张图可以看出,MYISAM 表的索引存储方式最大的缺点没有按照物理数据行顺序存储,这样无论对主键的检索还是对二级索引的检索都需要进行二次排序。

举个简单例子演示下,

以下 SQL 1 默认没有排序,乱序输出;需要按照 ID 顺序输出,就得用 SQL 2,显式加 ORDER BY 。

mysql
# SQL 1
mysql> select * from t1;
+-------+----------+--------+------+--------------+
| id    | username | gender | age  | phone_number |
+-------+----------+--------+------+--------------+
| 10001 | 小花     | 女     |   18 | 18501877098  |
| 10005 | 小李     | 女     |   21 | 15827654555  |
| 10006 | 小白     | 男     |   38 | 19929933000  |
| 10009 | 小何     | 男     |   35 | 19012378676  |
| 10002 | 小王     | 男     |   20 | 17760500293  |
| 10003 | 小赵     | 女     |   29 | 13581386000  |
| 10004 | 小青     | 女     |   25 | 13456712000  |
| 10007 | 小米     | 男     |   23 | 19800092354  |
| 10008 | 小徐     | 女     |   22 | 18953209331  |
+-------+----------+--------+------+--------------+
9 rows in set (0.00 sec)# SQL 2
mysql> select * from t1 order by id;
+-------+----------+--------+------+--------------+
| id    | username | gender | age  | phone_number |
+-------+----------+--------+------+--------------+
| 10001 | 小花     | 女     |   18 | 18501877098  |
| 10002 | 小王     | 男     |   20 | 17760500293  |
| 10003 | 小赵     | 女     |   29 | 13581386000  |
| 10004 | 小青     | 女     |   25 | 13456712000  |
| 10005 | 小李     | 女     |   21 | 15827654555  |
| 10006 | 小白     | 男     |   38 | 19929933000  |
| 10007 | 小米     | 男     |   23 | 19800092354  |
| 10008 | 小徐     | 女     |   22 | 18953209331  |
| 10009 | 小何     | 男     |   35 | 19012378676  |
+-------+----------+--------+------+--------------+
9 rows in set (0.00 sec)

接下来看看 INNODB 的主键索引和二级索引的组成方式。

INNODB 表:

INNODB 表本身是索引组织表,也就是说索引就是数据。下图表T1的数据行以聚簇索引的方式展示,非叶子节点保存了主键的值,叶子节点保存了主键的值以及对应的数据行,并且每个页有分别指向前后两页的指针。

INNODB 表不同于 MYISAM,INNODB 表有自己的数据页管理,默认 16KB。MYISAM 表数据的管理依赖文件系统,比如文件系统一般默认 4KB,MYISAM 的块大小也是 4KB,MYISAM 表的没有自己的一套崩溃恢复机制,全部依赖于文件系统。

INNODB 表这样设计的优点有两个:

1. 数据按照主键顺序存储。主键的顺序也就是记录行的物理顺序,相比指向数据行指针的存放方式,避免了再次排序。我们知道,排序消耗最大。现在表 t1 的直接拿出来就是按照主键 ID 排序。

mysqlmysql> select * from t1;+-------+----------+--------+------+--------------+| id    | username | gender | age  | phone_number |+-------+----------+--------+------+--------------+| 10001 | 小花     | 女     |   18 | 18501877098  || 10002 | 小王     | 男     |   20 | 17760500293  || 10003 | 小赵     | 女     |   29 | 13581386000  || 10004 | 小青     | 女     |   25 | 13456712000  || 10005 | 小李     | 女     |   21 | 15827654555  || 10006 | 小白     | 男     |   38 | 19929933000  || 10007 | 小米     | 男     |   23 | 19800092354  || 10008 | 小徐     | 女     |   22 | 18953209331  || 10009 | 小何     | 男     |   35 | 19012378676  |+-------+----------+--------+------+--------------+9 rows in set (0.00 sec)

2. 两个叶子节点分别含有指向前后两个节点的指针,这样在插入新行或者进行页分裂时,只需要移动对应的指针即可。

再来看下 INNODB 表的二级索引,如下图所示:

INNODB 二级索引的非叶子节点保存索引的字段值,上图索引为表 t1 的字段 age。叶子节点含有索引字段值和对应的主键值。

这样做的优点是当出现数据行移动或者数据页分裂时,避免二级索引不必要的维护工作。当数据需要更新的时候,二级索引不需要重建,只需要修改聚簇索引即可。

但是也有缺点:

1. 二级索引由于同时保存了主键值,体积会变大。特别是主键设计不合理的时候,比如用 UUID 做主键。下一篇我详细介绍如何设计合理的主键。

2. 对二级索引的检索需要检索两次索引树。第一次通过检索二级索引叶子节点,找到过滤行对应的主键值;第二次通过这个主键的值去聚簇索引中查找对应的行。

举个例子:

如下 SQL 语句,检索年龄为 23 的行记录:

mysql
select * from t1 where age = 23;

会拆分成以下两个 SQL 语句:

先通过索引字段 age 找到对应的主键值:10005.

mysql
select id from t1 where age=23;

再去聚簇索引上根据主键 ID = 10005 检索到需要的数据行,如果表第一次读取,就需要回表。

mysql
select * from t1 where id = 10005;

不过 MySQL 对这块做了很好的优化,提前做了数据预热(数据预热,这里就不讲了,可以参考 MySQL 手册,手册上介绍的很详细)。

本篇内容介绍到此,简单回顾下本篇内容。本篇主要介绍 MySQL 常见的两种引擎 MYISAM 和 INNODB 的索引组织方式以及各自的优缺点。有问题欢迎批评指正,下一篇我来介绍 MySQL 如何很好的对主键进行设计。


关于 MySQL 的技术内容,你们还有什么想知道的吗?赶紧留言告诉小编吧!

索引体积_第16期:索引设计(MySQL 的索引结构)相关推荐

  1. mysql 索引 美团_美团面试官:说说MySQL的索引

    从本文开始,选取牛客网上大厂的面试题,整理出相关内容的知识点. 什么是索引 小学时我们经常用到的字典里有音节索引和部首目录,当我们查字典时,常常用音节索引和部首目录帮助我们提高查找汉字的速度.MySQ ...

  2. mysql gis index 索引原理_从原理到优化,深入浅出数据库索引

    MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构. 数据库查询是数据库的最主要功能之一,我们都希望查询数据的速度能尽可能的快,因此数据库系统的设计者会从查询算法的 ...

  3. asp.net怎么实现按条件查询_【33期】分别谈谈联合索引生效和失效的条件

    点击上方"Java面试题精选",关注公众号 面试刷图,查缺补漏 >>号外:往期面试题,10篇为一个单位归置到本公众号菜单栏->面试题,有需要的欢迎翻阅. 这道题考 ...

  4. 联合索引会创建几个索引_【1033期】分别谈谈联合索引生效和失效的条件

    这道题考查索引生效条件.失效条件.像这类问题才其实很有意义,建议各位以后面试其他伙伴的时候,多侧重这类问题的提问,比考察一般概念性的问题好多了. 能大概考察应聘者对写的程序是有注重做优化,提高代码质量 ...

  5. mysql中groupby会用到索引吗_开发人员不得不知的MySQL索引和查询优化

    本文主要总结了工作中一些常用的操作及不合理的操作,在对慢查询进行优化时收集的一些有用的资料和信息,本文适合有 MySQL 基础的开发人员. 索引相关 索引基数 基数是数据列所包含的不同值的数量,例如, ...

  6. 大文本存mysql怎么建索引_如何正确合理的建立MYSQL数据库索引

    # 有这样一个表 P mysql> create table P (id int primary key, name varchar(10) not null, sex varchar(1), ...

  7. 联合索引会创建几个索引_面试官:谈谈你对mysql联合索引的认识?

    引言 这篇文章作为<面试官:谈谈你对mysql索引的认识>的续篇,我当时在写这篇的时候,考虑到篇幅问题所以略去了联合索引的内容,今天给大家补上. 本文预计分为两个部分:(1)联合索引部分的 ...

  8. cad刷新快捷键_第16期分享:常用电脑快捷键是哪些?

    电脑键盘快捷键的使用能很好的提高工作效率,所谓的快捷键就是使用键盘上某一个或某几个键的组合完成一条功能命令,从而达到提高操作速度的目的.善于使用快捷键能更快捷的使用电脑,那么电脑键盘快捷键有哪些呢?下 ...

  9. php mysql索引原理_加速PHP动态网站 关于MySQL索引分析优化

    本文主要讲述了如何加速动态网站的MySQL索引分析和优化. 一.什么是索引? 索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第 ...

最新文章

  1. 机器学习02-分类、逻辑回归
  2. 如何让敏捷中的每日站会发挥最大效果?
  3. Flask 第三方组件之 WTForms
  4. 浅谈“三层结构”原理与用意(转帖)
  5. Android:四大架构的优缺点,你真的了解吗?
  6. HTML内置css改变文字效果,CSS+HTML文字效果
  7. 网络编程中sockaddr和sockaddr_in的区别(socket)
  8. python绘制降水色斑图
  9. 汇编:Debug的常用命令
  10. CSA云安全指南V4.0 D9 D10
  11. Java企业微信开发_02_通讯录同步
  12. 游戏打的菜?当然是延迟的锅啦~
  13. 关于AQS中自旋的理解
  14. 推荐一篇好文《佛教真像大家所认为的那样消极吗?》
  15. 用pyxel 学写 Kill Virus 像素游戏
  16. 学习:数学----欧拉定理与扩展欧拉定理
  17. Linux紧急模式问题处理方法
  18. iOS WebRTC多人音视频建立的流程
  19. 生鲜商城系统如何营销?
  20. 算法:求两个数的最大公约数与最小公倍数的方法

热门文章

  1. 没毛病!00后和90后成为暑期出游两大主力群体
  2. iPhone XI Max带壳渲染图曝光:依然刘海屏 后置“浴霸”三摄实锤
  3. 罗永浩:还会给你们做手机 只是需要时间
  4. 又翻车?苹果被揪出夸大iPhone续航时间:iPhone XR虚标51%
  5. 【点阵液晶编程连载五】液晶驱动代码的移植
  6. 计算机三级数据库er图试题里,2019年3月计算机三级数据库考试基础试题及答案006...
  7. python不联网安装selenium_Anaconda python 离线安装selenium3.141很容易
  8. 智慧讲台必须支持的协议
  9. 法国 计算机 转专业,在法国留学怎样换专业
  10. oracle:oracle学习笔记(三)