相关博文原文地址:

博客园:yuanrw:MySQL索引的原理,B+树、聚集索引和二级索引的结构分析



在mysql中,存储引擎用类似的方法使用索引,先在索引中找到对应值,然后根据匹配的索引记录找到对应的行。

一、索引类型

1.1 B树

大多数存储引擎都支持B树索引。b树通常意味着所有的值都是按顺序存储的,并且每一个叶子也到根的距离相同。B树索引能够加快访问数据的速度,因为存储引擎不再需要进行全表扫描来获取数据。下图就是一颗简单的B数。



B树的查询流程:

如上图我要从找到E字母,查找流程如下:

(1)获取根节点的关键字进行比较,当前根节点关键字为M,E<M(26个字母顺序),所以往找到指向左边的子节点(二分法规则,左小右大,左边放小于当前节点值的子节点、右边放大于当前节点值的子节点);

(2)拿到关键字D和G,D<E<G 所以直接找到D和G中间的节点;

(3)拿到E和F,因为E=E 所以直接返回关键字和指针信息(如果树结构里面没有包含所要查找的节点则返回null);

(4)通过指针信息取出这条记录的所有信息;

1.2 B+树

下图为B+树的结构,B+树是B树的升级版,我们可以观察一下,B树和B+树的区别是什么?

B+树和B树的区别是:

  1. B树的节点中没有重复元素,B+树有。
  2. B树的中间节点会存储数据指针信息,而B+树只有叶子节点才存储。
  3. B+树的每个叶子节点有一个指针指向下一个节点,把所有的叶子节点串在了一起。

从下图我们可以直观的看到B树和B+树的区别:紫红色的箭头是指向被索引的数据的指针,大红色的箭头即指向下一个叶子节点的指针。



我们假设被索引的列是主键,现在查找主键为5的记录,模拟一下查找的过程:

B树,在倒数第二层的节点中找到5后,可以立刻拿到指针获取行数据,查找停止。

B+树,在倒数第二层的节点中找到5后,由于中间节点不存有指针信息,则继续往下查找,在叶子节点中找到5,拿到指针获取行数据,查找停止。

B+树每个父节点的元素都会出现在子节点中,是子节点的最大(或最小)元素。叶子节点存储了被索引列的所有的数据。

那B+树比起B树有什么优点呢?

  1. 由于中间节点不存指针,同样大小的磁盘页可以容纳更多的节点元素,树的高度就小。(数据量相同的情况下,B+树比B树更加“矮胖”),查找起来就更快。
  2. B+树每次查找都必须到叶子节点才能获取数据,而B树不一定,B树可以在非叶子节点上获取数据。因此B+树查找的时间更稳定。
  3. B+树的每一个叶子节点都有指向下一个叶子节点的指针,方便范围查询和全表查询:只需要从第一个叶子节点开始顺着指针一直扫描下去即可,而B树则要对树做中序遍历。

了解了B+树的结构之后,我们对一张具体的表做分析:

create table Student(
last_name varchar(50) not null,
first_name varchar(50) not null,
birthday date not null,
gender int(2) not null,
key(last_name, first_name, birthday)
);

对于表中的每一行数据,索引中包含了name,birthday列的值。

索引对多个值进行排序的依据是create table语句中定义索引时列的顺序,即如果名字相同,则根据生日来排序。

B+树的结构决定了这种索引对以下类型的查询有效:

全值匹配

和索引中所有的列进行匹配,例如查找姓名为Cuba Allen,生日为1960-01-01的人。

匹配最左前缀

查找姓为Allen的人,即只用索引的第一列。

匹配列前缀

匹配某一列的值的开头部分,例如查找所有以J开头的姓的人。

匹配范围值

查找姓在Allen和Barrymore之间的人。

精确匹配某一列并范围匹配另外一列

查找姓为Allen,名字是字母K开头的人。即第一列last_name全匹配,第二列first_name范围匹配。

只访问索引的查询

查询只需要访问索引,无需访问数据行。这种索引叫做覆盖索引。

1.3 哈希索引

哈希索引,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码。哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。如果多个列的哈希值相同,索引会以链表的方式存放多个指针记录到同一个哈希条目中。

因为索引自身只存储对应的哈希值,所以索引的结构十分紧凑,哈希索引查找的速度非常快。但是哈希索引也有它的限制:

  • 哈希索引不是按照索引顺序存储的,无法用于排序。
  • 不支持部分索引列匹配查找。
  • 不支持范围查找。

1.4 聚集索引(clusterd index)

每个存储引擎为InnoDB的表都有一个特殊的索引,叫聚集索引。聚集索引并不是一种单独的索引类型,而是一种数据存储方式。当表有聚集索引的时候,它的数据行实际上存放在叶子页中。一个表不可能有两个地方存放数据,所以一个表只能有一个聚集索引。

  因为是存储引擎负责实现索引,因此不是所有的存储引擎都支持聚集索引。InnoDB表中聚集索引的索引列就是主键,所以聚集索引也叫主键索引。

例如下面这张InnoDB表:

create table Student(
id int(11) primary key auto_increment,
last_name varchar(50) not null,
first_name varchar(50) not null,
birthday date not null
);

1.5 二级索引(secondary indexes)

对于InnoDB表,在非主键列的其他列上建的索引就是二级索引(因为聚集索引只有一个)。二级索引可以有0个,1个或者多个。二级索引和聚集索引的区别是什么呢?二级索引的节点页和聚集索引一样,只存被索引列的值,而二级索引的叶子页除了索引列值,还存这一列对应的主键值。

二、InnoDB和MyISAM的数据分布对比

以下表为例,我们看下InnoDB和MyISAM是如何存储这个表的:

create table layout_test(
col1 int(11) primary key,
col2 int(11) not null,
key(col2)
);





叶子节点存储了整个表的数据,而不是只有索引列,每个叶子节点包含了主键值、事务ID、用于事务和MVCC的回滚指针以及所有的剩余列(col2)。

二级索引分布如下:



二级索引的叶子节点中存储的不是“行指针”,而是主键值,并以此作为指向行的“指针”。这样的策略减少了当出现行移动或者数据页分裂时二级索引的维护工作。使用主键当做指针会让二级索引占更多空间,但好处是InnoDB在移动行时无需更新二级索引中的这个指针。

2.1 InnoDB表的数据分布

聚集索引(主键索引)分布如下:

聚集索引的优点:

可以把相关数据保存在一起,例如实现电子邮箱时,根据用户ID来聚集数据,读取少数的数据页就能获取某个用户的全部邮件。

聚集索引将索引和数据保存在同一个B树中,因此从聚集索引中获取数据比在非聚集索引中要快一些。

聚集索引的缺点:

插入速度严重依赖插入顺序。按照主键的顺序插入是加载数据到InnoDB表中速度最快的方式。假如磁盘中的某一个已经存满了,但是新增的行要插入到这一页当中,存储引擎就会把该也分裂成两个页面来容纳该行,这就是一次页分裂操作。页分裂会导致表占用更多的磁盘空间。

更新聚集索引列的代价很高,会强制InnoDB将每个被更新的行移动到新的位置。

用二级索引访问数据需要两个索引查找,不是一次。因为要先从二级索引的叶子节点获得主键值,再根据这主键去聚集索引中查到对应的行,所以需要两次B树查找。

MySQL索引的原理,B+树、聚集索引和二级索引的更多相关文章

  1. MySQL索引的原理,B+树、聚集索引和二级索引的结构分析

    索引是一种用于快速查询行的数据结构,就像一本书的目录就是一个索引,如果想在一本书中找到某个主题,一般会先找到对应页码.在mysql中,存储引擎用类似的方法使用索引,先在索引中找到对应值,然后根据匹配的 ...

  2. 重新学习MySQL数据库4:Mysql索引实现原理

    重新学习Mysql数据库4:Mysql索引实现原理 MySQL索引类型 (https://www.cnblogs.com/luyucheng/p/6289714.html) 一.简介 MySQL目前主 ...

  3. MySQL——索引实现原理

    在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,本文主要讨论MyISAM和InnoDB两个存储引擎的索引实现方式. MyISAM索引实现 MyISAM引擎使用B+Tr ...

  4. 面试题:MySQL索引为什么用B+树?

    面试题:MySQL索引为什么用B+树? 前言 讲到索引,第一反应肯定是能提高查询效率.例如书的目录,想要查找某一章节,会先从目录中定位.如果没有目录,那么就需要将所有内容都看一遍才能找到. 索引的设计 ...

  5. InnoDB索引实现原理以及注意点和建议

    一.InnoDB实现原理 虽然InnoDB也使用B+Tree作为索引结构,但具体实现方式却与MyISAM截然不同.因为InnoDB支持聚簇索引(主键索引),聚簇索引就是表,所以InnoDB不用像MyI ...

  6. [Phoenix] 五、二级索引

    摘要: 目前HBASE只有基于字典序的主键索引,对于非主键过滤条件的查询都会变成扫全表操作,为了解决这个问题Phoenix引入了二级索引功能.然而此二级索引又有别于传统关系型数据库的二级索引,本文将详 ...

  7. [转]HBASE 二级索引

    1.二级索引的核心思想是什么?2.二级索引由谁来管理?3.在主表中插入某条数据后,hbase如何将索引列写到索引表中去?4.scan查询的时候,coprocessor钩子的作用是什么?5.在split ...

  8. HBase协处理器同步二级索引到Solr

    一. 背景二. 什么是HBase的协处理器三. HBase协处理器同步数据到Solr四. 添加协处理器五. 测试六. 协处理器动态加载 一. 背景 在实际生产中,HBase往往不能满足多维度分析,我们 ...

  9. HBase的二级索引

    使用HBase存储中国好声音数据的案例,业务描述如下: 为了能高效的查询到我们需要的数据,我们在RowKey的设计上下了不少功夫,因为过滤RowKey或者根据RowKey查询数据的效率是最高的,我们的 ...

  10. 使用高斯Redis实现二级索引

    摘要:高斯Redis 搭建业务二级索引,低成本,高性能,实现性能与成本的双赢. 本文分享自华为云社区<华为云GaussDB(for Redis)揭秘第21期:使用高斯Redis实现二级索引> ...

随机推荐

  1. Turtlebot3新手教程:仿真

    本文章针对如何利用turtlebot3实现仿真功能进行讲解 测试环境:Ubuntu 16.04 和 ROS Kinetic Kame. 注意:TurtleBot3 Simulation 依赖 turt ...

  2. MySQL不会丢失数据的秘密,就藏在它的 7种日志里

    本文收录在 GitHub 地址 https://github.com/chengxy-nds/Springboot-Notebook 进入正题前先简单看看MySQL的逻辑架构,相信我用的着. MySQ ...

  3. Spring(2) --Bean相关

    你对Spring中的bean了解吗?都有哪些作用域(Scope)? Spring 官方文档对 bean 的解释是: In Spring, the objects that form the backb ...

  4. TCP/IP五层模型概述

    • 为什么要分层?    ○ 协议太多,将众多协议分层解决,能提高效率,复杂问题简单化,更容易发现问题,并针对性解决问题.• OSI七层模型     ○ 同层使用相同的协议,下层为上层提供服务.   ...

  5. Dubbo 配置的加载流程

    配置加载流程 在SpringBoot应用启动阶段,Dubbo的读取配置遵循以下原则 Dubbo支持了多层级的配置,按照预先定义的优先级自动实现配置之间的覆盖,最终所有的配置汇总到数据总线URL后,驱动 ...

  6. python学习笔记 | macOS Big Sur动态壁纸食用指南

    目录 前言 爬虫篇 壁纸使用篇 后记 前言 北京时间23日凌晨1点,苹果WWDC2020大会开幕.在发布会上,苹果正式发布了新版macOS,并将其命名为"Big Sur". 相比于 ...

  7. ctfhub技能树—RCE—过滤cat

    打开靶机 查看页面信息 构造payload 127.0.0.1 || ls 题目提示过滤了cat,但我还是想试试 果然不行 网页访问没有结果,应该和上题一样被注释了,使用和同样的方法进行解题 利用命令 ...

  8. [MRCTF2020]你传你🐎呢之.htaccess

    前言 最近,也是遇到了文件上传的文件,自己搭的靶场都不能用,今天,在这里又遇到了这个题.简单总结下,内容来自互联网,若有侵权,联系我. .htaccess简介 .htaccess文件(分布式配置文件) ...

  9. 一个非常棒的Go-Json解析库

    json是一种数据格式,经常被用作数据交换,页面展示,序列化等场景,基本每种语言都有对应的json解析框架,Go语言也不例外,并且内置了json库,基本能够满足一些普通开发场景,但有些复杂场景下就不太 ...

  10. MySQL ---- 锁知识

    锁 我们知道mysql中支持很多个存储引擎,在不同的存储引擎下所能支持的锁是不同的,我们通过MyISAM和InnoDB来进行一下对比. 表级锁定(table-level) ​ 表级别的锁定是MySQL ...