mysql16个索引,第16期:索引设计(MySQL 的索引结构)

bVbFqWr

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

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

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

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

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

MYISAM 表:

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

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

bVcILVz

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

主键字段索引树:

bVcILVC

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

年龄字段索引树:

bVcILVD

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

从上面两张图能够看出,MYISAM 表的索引存储方式最大的缺点没有按照物理数据行顺序存储,这样不管对主键的检索仍是对二级索引的检索都须要进行二次排序。 blog

举个简单例子演示下,

如下 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 表的没有本身的一套崩溃恢复机制,所有依赖于文件系统。

bVcILVL

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

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

mysql

mysql> 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)

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

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

bVcILVN

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

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

可是也有缺点:

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

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

举个例子:

以下 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 的技术内容,大家还有什么想知道的吗?赶忙留言告诉小编吧!

bVbFqV6

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值