专栏首页算法channelMySQL|索引背后

MySQL|索引背后

01

索引

以MySQL中的索引为例子总结。

数据库查询是数据库的最主要功能之一,实现高效的查询速度一定是MySQL非常关心的事情。

索引(Index)正是帮助MySQL高效获取数据的数据结构。

目前大部分数据库系统及文件系统都采用B-Tree或其变种B+Tree作为索引结构,因此先看下这两种树的基本概念,至于B-Tree/B+Tree涉及的主要操作比如,裂变等,大家可以进一步参阅其他书籍或博客学习。

02

B-树

m阶B-树也称作(ceil(m), m)树,如(2,3)树,称为3阶B树,(2,4)树称为4阶B树。

如下为4阶B-树,每个节点至少含有2个分支,至多含有4个分支,也就是说,每个节点至少含有1个数据节点,至多含有3个数据节点。

03

B+树

B+树和m阶的B-树的差异在于:

  1. 内节点(非叶子节点),只用来索引;
  2. 所有的外节点(叶子结点) 中包含了: 1) 全部关键字的信息 2) 指向含这些关键字记录的指针 3) 外节点(叶子结点) 本身依关键字的大小自小而大顺序链接。

如下所示,所有节点都有key域;叶节点的数据域上才真正存储着数据,而非叶节点的数据域只保存多个指针。

04

为什么是B+树?而不是红黑树

为什么MySQL选择了B+树,而不是红黑树作为数据库的索引呢?

B+Tree中一次检索最多需要h-1次I/O(根节点常驻内存),树的高度为O(logdN)。一般实际应用中,一个节点的分支数(出度d)是非常大的数字(通常大于100),因此树的高度会非常小(通常不超过3)。索引设计为B+数据结构,一次检索所需要的I/O次数就会很小。我们又知道,访问内存的延迟大约为ns级,而访问磁盘的延迟为ms级,这相当于,访问内存延迟如果1天的话,访问外存延迟需要2000年。

根据磁盘预读原理,B+树将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入。每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里。

而红黑树这种结构,h明显要深的多。并且,红黑树中逻辑上很近的节点(父子)物理上可能很远,无法利用局部性。

综上,B+树更适合做索引。

05

MyISAM和InnoDB存储引擎

在MySQL中,不同存储引擎对索引的实现方式是不同的,总结下MyISAM和InnoDB两个存储引擎的索引实现方式。

MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。

第一列作为主索引的MyISAM引擎存储结构,要求主索引取值唯一。

虽然InnoDB也使用B+Tree作为索引结构,但具体实现方式却与MyISAM不同。InnoDB的叶子节点的数据域保存了完整的数据记录,索引的key是数据表的主键

06

InnoDB的主键选择与插入优化

在使用InnoDB存储引擎时,建议使用一个与业务无关的自增字段作为主键。

InnoDB将数据记录本身存于主索引(一颗B+Tree)的叶子节点上。每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置,如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页。如下图所示:

这样就会形成一个紧凑的索引结构,近似顺序填满。

如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置:

此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。

因此,只要可以,请尽量在InnoDB上采用自增字段做主键。

知道了这些基本知识,如何加以运用呢?see you!

本文部分参考了关于介绍索引的文章:

http://blog.codinglabs.org/articles/theory-of-mysql-index.html

以上,如果疏漏错误,请指正。

希望时间的流逝不仅仅丰富了我们的阅历,更重要的是通过提炼让我们得以升华,走向卓越。

本文分享自微信公众号 - 算法channel(alg-channel),作者:alg-flody

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-03-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 大白话总结著名的 word2vec

    本文作者:Alicia , 现在美国名校读博士后,从事 AI 研究及教学工作,拥有 10 年以上工作与科研经历。

    double
  • 跨越时空:找回 RNN 消失的梯度

    斯坦福 NLP 的第 9 课后半部分给出了答案:主要应对梯度消失的措施是隐含层中采用更复杂的隐含单元。读者朋友们,你们可以回想下 RNN 的网络结果,隐含层中,...

    double
  • 二叉树非递归版的后序遍历算法

    本公众号主要推送关于对算法的思考以及应用的消息。算法思想说来有,分而治之,搜索,动态规划,回溯,贪心等,结合这些思想再去思考如今很火的大数据,云计算和机器学习,...

    double
  • MySQL索引背后的数据结构及算法原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题。特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎 对索引的支持也各不相同,因...

    wangxl
  • MySQL索引那些事

    大家有没有遇到过慢查询的情况,执行一条SQL需要几秒,甚至十几、几十秒的时间,这时候DBA就会建议你去把查询的 SQL 优化一下,怎么优化?你能想到的就是加索引...

    编程大道
  • Python高级语法示例

    版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons)

    魏晓蕾
  • 一文带你深入理解Mysql索引底层数据结构与算法

    首先看一下,在数据库没有加索引的情况下,SQL中的where语句是如何查找目标记录的,首先看到下图的Col2字段,如果我们要查找where col2 = 89的...

    黎明大大
  • BAT大厂都会问的MySQL底层数据结构

    左边子节点的数据小于父节点数据,右边子节点的数据大于父节点数据。如果col2是索引,查找索引为89的行元素,那么只需要查找两次,就可以获取到行元素所在的磁盘指针...

    程序员小强
  • MySQL索引背后的数据结构及算法原理

    MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是数据结构。

    互扯程序
  • SQL学习笔记之B+树

    任意节点,它的左子树如果不为空,那么左子树上所有节点的值都小于根节点的值; 任意节点,他的右子树如果不为空,那么右子树上的所有节点的值大于根节点的值。

    Jetpropelledsnake21

扫码关注云+社区

领取腾讯云代金券