写在前面

  想要做好后台开发,终究是绕不过索引这一关的。先问自己一个问题,InnoDB为什么选择B+树作为默认索引结构。本文主要参考MySQL索引背后的数据结构及算法原理剖析Mysql的InnoDB索引

索引

  当数据量到达一定规模时,我们通常会对经常使用的字段建立索引,来加快数据的查询。首先需要强调的是索引的本质是数据结构,前辈们经过不断完善得到了几种复杂度较低并且能够降低磁盘IO的数据结构,这里要说的是B树与B+树,他们被广泛应用在文件系统与数据库系统中。

B-Tree

   B树逻辑上是一颗多叉树,3阶B树如下:

  m阶B树满足以下几个条件:

  • 非叶子节点最少有m/2颗子树(即B树的度为m/2)
  • 叶子节点在同一层,每个节点最多有m-1个升序排列的key(索引列)和m个指针,key与指针相互间隔

搜索二叉树的查询复杂度为O(log2N),而B树的复杂度为O(logm/2N),对于N=62*1000000000个节点,如果度为1024,则logM/2N <=4,可以说它是效率很高的数据结构。

B+树

  B+树是B树的变种,区别有三点:

  • 非叶子节点只存储key,不存储data;叶子节点存储所有key与data,不存储指针
  • 叶子节点增加了顺序访问指针
  • 每个节点最多有m个升序排列的key

  上述区别换来的优点包括:

  • 非子节点可以存放更多的key,具有更好的空间局部性,提高缓存命中率
  • 叶子节点相链便于区间查找,顺序查找替代B树的递归查找。

为什么选择B+树

  首先要意识到数据检索的时间主要耗费在磁盘IO(寻道时间、旋转时间)上,因此要尽量减少IO次数。对树形结构的数据来说,树的每一层代表需要一次磁盘IO查询,因此设计了“扁平”的B树与更扁的B+树。另外,由著名的局部性原理,访问的数据通常比较集中,磁盘每次IO时会预读数据,预读的长度为页(4k)的整数倍,B/B+树新建节点会申请一个页的空间,因此取一个节点只需要一次IO(非叶子节点可存储到内存中)。

索引创建过程

mysql创建索引是通过online create index,减少业务停写时间,创建索引期间业务能正常工作。

步骤:

  1. 等待当前所有事务执行结束;新事务更新数据会把新建索引记录到Row Log中
  2. 构建索引,从主表读出数据并排序。使用临时文件进行外部排序方式,单线程两路归并。
  3. 把增量数据从Row Log更新到索引表中

MySQL存储引擎

首先区分聚簇索引(按主键聚集)与非聚簇索引:

  • 二者使用B+树作为数据结构
  • 聚簇索引的data存于主键索引的叶子节点中,得到key同时得到data,非聚簇索引数据存于独立的地方,叶节点保存的是数据的地址
  • 聚簇索引的辅助键索引(非主键索引,例如employee表中对name建索引)叶节点存储主键而非数据(为了节省空间,缺陷是需要到主键索引中二次查询);非聚簇索引叶节点保存数据的地址。

  聚簇索引的优势在于找到主键同时得到data,省去二次磁盘IO;另外B+树在插入或删除节点时周围节点地址会发生变化,对非聚簇索引来说需要更新所有B+树的地址指针,增加开销。

InnoDB

  InnoDB使用聚簇索引(MyISAM使用非聚簇索引),其磁盘管理逻辑单位是Page(不同于上述内存中的页!),每个Page大小为16k,使用32位int标识,对应innoDB最大64TB的存储容量。

  每个Page包括头部、主体、尾部三部分:

  其中头部包括id与相邻Page指针(构成双向链表);

  主体即B+树节点的存储,其中包括很多Record(节点)包括四类:

  • 主索引非叶子节点:定位Page
  • 主索引叶子节点:包括key与该key对应的所有列(mysql表中的一行)
  • 辅助索引非叶子节点:定位Page
  • 辅助索引叶子节点:包括索引键值与主键值(key)

  

 主键选择

  因为数据存于主索引中,要求一个节点的各条数据记录按主键顺序存放,当一页达到装载因子(15/16)会自动开辟新的页。如果使用自增主键,每次插入新纪录都顺序添加到索引节点的后续位置,否则会节点中key会一直移动。

  最左匹配原则

  在联合索引中对a,b两个字段建立索引(a, b),在查询时只有包括a时才会查询索引。

  如上图(a, b)联合索引,在a相同时,b按顺序排列。在遇到范围查询时之后的字段会停止匹配。因为a是范围,b无序。  

MySQL之InnoDB索引面试学习笔记的更多相关文章

  1. MySQL之Innodb恢复的学习笔记

    MySQL · 引擎特性 · InnoDB 崩溃恢复过程 enum { SRV_FORCE_IGNORE_CORRUPT = 1, /*!< let the server run even if ...

  2. MySQL索引知识学习笔记

    目录 一.索引的概念 二.索引分类 三.索引用法 四 .索引架构简介 五.索引适用的情况 六.索引不适用的情况 继我的上篇博客:Oracle索引知识学习笔记,再记录一篇MySQL的索引知识学习笔记,本 ...

  3. MySQL基础之事务编程学习笔记

    MySQL基础之事务编程学习笔记 在学习<MySQL技术内幕:SQL编程>一书,并做了笔记.本博客内容是自己学了<MySQL技术内幕:SQL编程>事务编程一章之后,根据自己的理 ...

  4. MySQL的InnoDB索引原理详解

    摘要 本篇介绍下Mysql的InnoDB索引相关知识,从各种树到索引原理到存储的细节. InnoDB是Mysql的默认存储引擎(Mysql5.5.5之前是MyISAM,文档).本着高效学习的目的,本篇 ...

  5. MySQL的InnoDB索引原理详解 (转)

    摘要: 本篇介绍下Mysql的InnoDB索引相关知识,从各种树到索引原理到存储的细节. InnoDB是Mysql的默认存储引擎(Mysql5.5.5之前是MyISAM,文档).本着高效学习的目的,本 ...

  6. 剖析Mysql的InnoDB索引

    摘要: 本篇介绍下Mysql的InnoDB索引相关知识,从各种树到索引原理到存储的细节. InnoDB是Mysql的默认存储引擎(Mysql5.5.5之前是MyISAM,文档).本着高效学习的目的,本 ...

  7. 《MySQL实战45讲》学习笔记4——MySQL中InnoDB的索引

    索引是在存储引擎层实现的,且在 MySQL 不同存储引擎中的实现也不同,本篇文章介绍的是 MySQL 的 InnoDB 的索引. 下文将以这张表为例开展. # 创建一个主键为 id 的表,表中有字段 ...

  8. Alibaba Java开发手册索引规约学习笔记

    最近一段时间再看阿里巴巴 Java开发手册索引规约,写篇帖子总结一下,索引规约内容如下 为了通用,更为了避免造数据的痛苦,文中所涉及表.数据,均来自于MySQL官网提供的示例库employees,可通 ...

  9. MySql基本的语法(学习笔记)

    MySQL语法大全_自己整理的学习笔记 select * from emp;  #凝视 #--------------------------- #----命令行连接MySql--------- #启 ...

随机推荐

  1. 并行forearch的使用及测试(Parallel.Foreach)

    using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tas ...

  2. c# 中对于每次修改的程序 都必须重新手动生成 才能编译的问题

    问题描述:原来用VS2017,升级了VS2019,发现修改了Winform界面,F5运行竟然还是原来的界面 问题解决: 需要修改两个地方 工具>> 选项>> 项目和解决方案&g ...

  3. Java的设计模式(3)--工厂模式

    工厂模式是定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到子类. 工厂模式涉及四种角色: 抽象产品(Product):抽象类或者接口,负责定义具体产品必须实现的方法 ...

  4. C++:标准模板库vector

    一:介绍 vector是C++标准模板库,是一个容器,底层是数组,为连续内存. 命名空间为std,所属头文件为<vector>   注意:不是<vector.h> vector ...

  5. yii2中通过migration创建数据表

    ### yii2中通过migration创建数据表 准备工作: 1.首先保证php写入了环境变量 2.在项目内创建migrations目录(base版的需要手动创建) 3.配置文件中正确配置了数据库信 ...

  6. python学习-14 基本数据类型3

    1.字符串 获取字符串的字符,例如: test = 'abcd' a= test[0] # 通过索引,下标,获取字符串中的某一个字符 print(a) b = test[0:1] # 通过下标的 范围 ...

  7. WUSTOJ 1275: 男神的逆袭(Java)

    1275: 男神的逆袭 题目   计算两个日期相差的天数.更多内容点击标题. 分析   下面说一下我的思路(自己写的,无扩展性): 给定一个日期,首先计算这个日期是这一年的第多少天. 给定两个日期,直 ...

  8. python03-break、continue、for循环、数据bytes类型、字符串与字节的关系、变量指向与深浅拷贝、set集合、文件操作

    目录: 1.break.continue 2.for循环 3.数据bytes类型 4.字符串与字节的关系 5.变量指向与深浅拷贝 6.set集合 7.文件操作 一.break.continue bre ...

  9. hdu 2844 多重背包的转化问题 以及这个dp状态的确定

    在杭电上测试了下 这里的状态转移方程有两个.,. 现在有价值val[1],val[2],…val[n]的n种硬币, 它们的数量分别为num[i]个. 然后给你一个m, 问你区间[1,m]内的所有数目, ...

  10. JavaScript检测浏览器

    Detect Browser <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...