Mysql InnoDB索引原理

Mysql InnoDB索引原理

理解Mysql索引的原理和数据结构有助于我们更好的使用索引以及进行SQL优化,索引是在存储引擎层面实现的,所以不同的引擎实现的索引也有一定的区别,但是在生产环境中,我们最常用的就是InnoDB引擎和B树索引,OK,那本文要讨论的重点也同样是InnoDB引擎下的B树索引

我们建立一个表来进行测试,表的DDL如下所示,我们要关注的是表t_book上的主键索引id和name author publish_date三列组成的索引test_index。

CREATE TABLE `t_book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `author` varchar(50) NOT NULL,
  `publish_date` date NOT NULL,
  PRIMARY KEY (`id`),
  KEY `test_index` (`name`,`author`,`publish_date`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

B树数据结构

Mysql中的B树索引是使用B+树实现的,关于B+树的数据结构个人认为美团点评技术博客中Mysql索引原理及慢查询优化一文中介绍的非常详实,B+树的数据结构如下图所示。

btree.jpg

图中浅蓝色块即磁盘块,根节点磁盘块中存储17和35两个数据,其中指针P1指向小于17的数据,指针P2指向大于17小于35的数据,指针P3指向大于35的数据。显然通过B+树索引查询数据与B+树的高度有关,如上图的B+树索引查找一个叶子节点的数据只需要三次磁盘IO,对于Mysql来说三层的B+树可以索引上百万的数据,这对于查询效率的提升是巨大的。

总结起来Mysql中B树索引有以下关键特点:

  1. 真实数据存储在叶子节点上,例如根节点的磁盘块中17和35并不是真实数据
  2. B树索引中的值是按顺序存储的,这一方面说明可以利用B树索引可以用于完成ORDER BY排序操作,当SQL可以使用索引排序时,EXPLAIN查看查询计划EXTRA列是不会出现USING FILESORT的(USING FILESORT为文件排序);另一方面,这也解释了Mysql索引的最左前缀匹配原则。
  3. Mysql在上图所示的B+树数据结构的基础上,为每一个叶子节点增加了指向下一个叶子节点的指针,用于方便叶子节点的范围遍历。

如果对以上介绍的特点有疑问,可以直接往下看,我们将在聚簇索引和二级索引的介绍中举例说明以上特点的原理。

Mysql中的B树索引有两种数据存储形式,一种为聚簇索引,一种为二级索引。

聚簇索引

InnoDB一般会使用表的主键来作为聚簇索引,如果一个表没有主键(不建议这么玩)InnoDB会选用一个唯一非空索引来代替,如果没有这样的索引,InnoDB会隐式建立一个聚簇索引。聚簇的含义即是数据行和相邻的键值紧凑的存储在一起,占据一块连续的磁盘空间,因此通过聚簇索引访问数据可以有效减少随机IO,通常使用聚簇索引查找比非聚簇索引查找速度更快。以我们建立的表t_book为例,聚簇索引即为自增主键id,其B树索引数据结构可以用下图来表示。

聚簇索引.jpg

聚簇索引有以下关键特点:

  1. 在InnoDB中聚簇索引即为表的存储结构,表的其他列数据也会存储到叶子节点中,从聚簇索引中获取数据比二级索引获取数据要快。
  2. 聚簇索引是按顺序存储的,因此Insert速度严重依赖于插入顺序,如果在聚簇索引的中间一行插入数据,会导致后面行都会被移动,可能面临页分裂的问题。所以,在插入频繁的表中不建议使用varchar类型的列作为主键,如果真的有这种情况,建议为表增加一个自增主键作为代理键,哪怕这个自增主键没有任何意义(最好避免不连续且值的范围分布很大的聚簇索引)。
  3. 由于把相关数据保存在连续的硬盘空间上,所以通过聚簇索引聚集数据只需要一次磁盘IO,可以有效加快查询速度。

图中仅画了叶子节点和和其父亲节点,第一个表格存储了id为1~10的数据,第二个表存储了id为11
~20的数据,注意,P1即为上文中提到的指向下一个叶子节点的指针。

二级索引

InnoDB的B树索引中除了聚簇索引,就都是二级索引了,二级索引的含义是索引的叶子节点除了存储了索引值,还存储了主键id,在使用二级索引进行查询时,查找到二级索引B树上的叶子节点后还需要去聚簇索引上去查询真实数据,但是这里有一种特殊情况,即查询所需的所有字段在二级索引中都可以获取,此时就不需要再去回表查数据了,这种情况就是索引覆盖(EXPLAIN中EXTRA列中会出现USING INDEX,本文只关注索引结构,不详细讨论索引覆盖等技术的使用,如果深入理解索引的数据结构,索引覆盖等技术也没有那么神秘)。

在我们的测试表t_book中,test_index即为二级索引,由于我们把除了主键id所有的列都作为一个联合索引,所以在这个表上的查询都可以使用索引覆盖技术,但是具体生产环境中也不建议总是采用这种做法,索引列的增加也会增大插入更新数据时的索引更新成本,具体的优化要视具体情况决策。t_book上的二级索引test_index的索引结构由下图表示。

二级索引.jpg

通过以上结构,我们可以推断出二级索引的以下关键特点:

  1. InnoDB二级索引中存储主键值,当发生行移动时,不影响二级索引的维护工作
  2. 通过以上的索引结构我们现在可以非常清晰的理解B树索引的最左前缀匹配原则,例如,如果匹配以Book为后缀的书名,InnoDB引擎需要全量扫描索引test_index才能找到匹配的记录(EXPLAIN中Type列为Index,实际仍然是全表扫描),但是如果要搜索以Book为前缀的记录,则会直接命中索引找到查找的记录
  3. 另外特别特别特别重要的是,可以通过这个结构图可以理解索引的列前缀匹配原则,我们无法通过这个二级索引树去直接命中搜索作者为Brian Goetz的记录,同样,当我们搜索书名为Thinking in Java,作者名字为B开头的名字,出版时间为2008-3(好吧,这个例子不太合理,假如我们有N本书的书名叫Thinking in Java且作者名字都是B开头的),那我们可以使用二级索引的name和author字段,但是在查询出的N条记录中无法再使用索引中publish_date字段,即Where子句中如果使用了范围条件,后面的字段就无法再使用索引了,当然我们也不能跳过任何一个字段去使用索引(只用name和publish_date字段去搜索)。

索引覆盖:


索引覆盖.png

最左前缀匹配:


最左前缀.png

列前缀:
列前缀.png

二级索引可以说是我们在Mysql中最常用的索引,通过理解二级索引的索引结构可以更容易理解二级索引的特性和使用。

哈希索引

最后聊点轻松的索引结构,哈希索引就是通过哈希表实现的索引,即通过被索引的列计算出哈希值,并指向被索引的记录。
哈希索引有如下特性:

  1. 哈希索引只包含哈希值和行指针,不包含数据,使用哈希索引必须回表查找
  2. 哈希索引顺序并不是按顺序存储的,所以不能用于排序
  3. 哈希索引也不支持部分索引列匹配查找,必须匹配全部列,才能计算出哈希值找到对应记录

参考文献

Mysql索引原理及慢查询优化

高性能Mysql 第三版

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容

  • 《高性能MySQL》&《MySQL技术内幕 InnoDB存储引擎》笔记 第一章 MySQL架构与历史 MySQL的...
    xiaogmail阅读 12,748评论 0 39
  • Mysql概述 数据库是一个易于访问和修改的信息集合。它允许使用事务来确保数据的安全性和一致性,并能快速处理百万条...
    彦帧阅读 13,665评论 10 461
  • 聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。比如,InnoDB的聚簇索引使用B+Tree的数据结构存储...
    sherlock_6981阅读 1,859评论 0 2
  • 学会别人手把手教给你的技能,很多时候我们都以为自己已经学会了,可是很多时候你没有真正的学会,比如走路,...
    台东一店高悦阅读 679评论 2 0
  • 洁和刚分手了,认识两人的好朋友无不唏嘘。 洁和刚在大学认识的,当时洁刚到学校报到,老生迎新生,穿着一袭白色连衣裙的...
    Sunny萍七阅读 198评论 6 2