InnoDB索引存储结构
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11429438.html
InnoDB默认创建的主键索引是聚簇索引(Clustered Index),其它索引都属于辅助索引(Secondary Index),也被称为二级索引或非聚簇索引。
接下来通过一个简单的例子,说明下这两种索引在存储数据中的具体实现。
首先创建一张商品表,如下:
CREATE TABLE `merchandise` (
`id` int(11) NOT NULL,
`serial_no` varchar(20) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`unit_price` decimal(10, 2) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
然后新增了以下几行数据,如下:

使用的是InnoDB存储引擎,由于InnoDB使用的是聚簇索引,聚簇索引中的叶子节点则记录了主键值、事务id、用于事务和MVCC的回流指针以及所有的剩余列,如下图所示:

基于上面的图示,如果需要根据商品编码serial_no查询商品,就需要将商品编码serial_no列作为一个索引列。此时创建的索引是一个辅助索引,但叶子节点存储的就不是行指针了,而是主键值,并以此来作为指向行的指针。这样的好处就是当行发生移动或者数据分裂时,不用再维护索引的变更。
回表
如果使用主键索引查询商品,则会按照B+树的索引找到对应的叶子节点,直接获取到行数据:
select * from merchandise where id = 7
如果使用serial_no查询商品,即使用辅助索引进行查询,则会先检索辅助索引中的B+树的serial_no,找到对应的叶子节点,获取主键值,然后再通过聚簇索引中的B+树检索到对应的叶子节点,然后获取整行数据。这个过程叫做回表。
回表就是先通过辅助索引扫描出数据所在的行,再通过行主键id取出索引中未提供的数据,即基于非主键索引的查询需要多扫描一棵索引树。
覆盖索引
假设只需要查询商品的名称、价格信息,有什么方式来避免回表呢?可以建立一个组合索引,即商品编码、名称、价格作为一个组合索引。如果索引中存在这些数据,查询将不会再次检索主键索引,从而避免回表。
从辅助索引中查询得到记录,而不需要通过聚簇索引查询获得,MySQL中将其称为覆盖索引。使用覆盖索引的好处很明显,不需要查询出包含整行记录的所有信息,因此可以减少大量的I/O操作。
通常在InnoDB中,除了查询部分字段可以使用覆盖索引来优化查询性能之外,统计数量也会用到。例如, SELECT COUNT(*)时,如果不存在辅助索引,此时会通过查询聚簇索引来统计行数,如果此时正好存在一个辅助索引,则会通过查询辅助索引来统计行数,减少I/O操作。
CREATE TABLE `test` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`a` varchar(32) NOT NULL,
`b` varchar(32) NOT NULL,
`c` varchar(64) NOT NULL,
`d` varchar(128) NOT NULL,
`e` varchar(256) NOT NULL,
`create_time` timestamp(3) NOT NULL DEFAULT current_timestamp(3),
`update_time` timestamp(3) NOT NULL DEFAULT current_timestamp(3) ON UPDATE current_timestamp(3),
PRIMARY KEY (`id`),
KEY `idx_a_b` (`a`,`b`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4;

Reference
https://time.geekbang.org/column/article/116369
https://zhuanlan.zhihu.com/p/27700617
InnoDB索引存储结构的更多相关文章
- 一文搞懂InnoDB索引存储结构
参考资料:掘金小册:MySQL 是怎样运行的:从根儿上理解 MySQL B+树 我们知道,InnoDB是用B+树作为组织数据形式的数据结构.不论是存放用户记录的数据页,还是存放目录项记录的数据页,我们 ...
- innodb的存储结构
如下所示,innodb的存储结构包含:表空间,段,区,页(块),行 innodb存储结构优化的标准是:一个页里面存放的行数越多,其性能越高 表空间:零散页+段 独立表空间存放的是:数据.索引.插入缓冲 ...
- InnoDB 逻辑存储结构
本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/80 如果创建表时没有显示的定义主键,mysql会按如下方式创建主 ...
- MySQL InnoDB 逻辑存储结构
MySQL InnoDB 逻辑存储结构 从InnoDB存储引擎的逻辑结构看,所有数据都被逻辑地存放在一个空间内,称为表空间,而表空间由段(sengment).区(extent).页(page)组成.p ...
- MYSQL Innodb逻辑存储结构
转载于网络 这几天在读<MySQL技术内幕 InnoDB存储引擎>,对 Innodb逻辑存储结构有了些了解,顺便也记录一下: 从InnoDB存储引擎的逻辑存储结构看,所有数据都被逻辑地存放 ...
- Innodb页面存储结构-2
上一篇<Innodb页面存储结构-1>介绍了Innodb页面存储的总体结构,本文会介绍页面的详细内容,主要包括页头.页尾和记录的详细格式. 学习数据结构时都说程序等于数据结构+算法,而在i ...
- InnoDB逻辑存储结构
从InnoDB存储引擎的逻辑存储结构看,所有数据都被逻辑地存放在一个空间中,称之为表空间(tablespace).表空间又由段(segment).区(extent).页(page)组成.页在一些文档中 ...
- InnoDB表存储结构及keyring加密
ibdata是InnoDB最重要的系统表空间文件,它记录了InnoDB的核心信息,包括事务系统信息.元数据信息,记录InnoDB change buffer的btree,防止数据损坏的double w ...
- sql server 索引阐述系列二 索引存储结构
一.概述. "流光容易把人抛,红了樱桃,绿了芭蕉“ 转眼又年中了,感叹生命的有限,知识的无限.在后续讨论索引之前,先来了解下索引和表数据的内部结构,这一节将介绍页的存储,页分配单元类型,区的 ...
随机推荐
- 人生苦短_我用Python_def(函数)_004
# coding=utf-8 # function函数:内置函数 # 例如: len int extent list range str # print insert append pop rever ...
- Ubuntu分区小知识与分区方案
Most PC operating systems still work with an ancient disk partition scheme that historically makes d ...
- centos6 / centos7 安装apache
=================centos6.1 安装apache===================== 安装: yum -y install httpd 启动 /etc/init.d/htt ...
- 【leetcode】543. Diameter of Binary Tree
题目如下: 解题思路:最长的周长一定是树中某一个节点(不一定是根节点)的左右子树中的两个叶子节点之间的距离,所以最简单的办法就是把树中所有节点的左右子树中最大的两个叶子节点之间的距离求出来,最终得到最 ...
- 微信小程序中显示html富文本的方法
微信小程序中显示html富文本的方法 使用方法:git地址:https://github.com/icindy/wxParse 一.下载wxParse文件 二.在要引入的页面的js文件中,引入文件 j ...
- 【C++11新特性】 C++11智能指针之shared_ptr
C++中的智能指针首先出现在“准”标准库boost中.随着使用的人越来越多,为了让开发人员更方便.更安全的使用动态内存,C++11也引入了智能指针来管理动态对象.在新标准中,主要提供了shared_p ...
- flutter网格布局之GridView组件
前面总结了使用ListView来实现列表,但是,有的时候,数据量很大,需要使用矩阵方式排列才能更清晰的展示数据,在flutter中,可以使用网格列表组件GridView来实现这个布局. GridVie ...
- [CSP-S模拟测试]:回文串(hash+二分)
题目描述 $ASDFZ$的机房中不仅有红太阳,还有蓝太阳和原谅色太阳.有一天,太阳们来到机房,发现桌上有不知道哪个蒟蒻放上的问题:令$F(A,B)$表示选择一个串$A$的非空前缀$S$和串$B$的非空 ...
- 测开之路五十七:实现runner和测试报告
准备测试用例 from fox.case import Casefrom src import Calculator class TestCalculator(Case): def setUp(sel ...
- CATiledLayer显示超大图片的解决方案
先对图片进行了裁剪 -> 很多小图片, 然后再根据显示 进行绘制 - (void)viewDidLoad { [super viewDidLoad]; [self cutImageAndSave ...