InnoDB中,表数据文件本身就是以主键为索引的B+树,树的叶子节点存放一条条表数据,此索引树被称为表的聚簇索引。聚簇索引也称为聚集索引,聚类索引,簇集索引,聚簇索引确定表中数据的物理顺序。

InnoDB聚簇索引

InnoDB表主键

InnoDB中每张表都会有一个主键,表中的每一行数据都是按照主键的顺序在聚簇索引中存储的,InnoDB中有两种方式确定一行数据的主键:

  • 显式声明:用户可以在建表的时候通过primary key关键字来声明主键列;
  • 唯一索引:如果用户没有声明主键列,那么InnoDB会使用第一个非空唯一列作为主键;
  • 自动生成:如果满足以上两种条件的列都不存在,那么InnoDB会将RowId作为主键;

聚簇索引示例

首先我们在数据库中建立一张用户表,包含用户ID、姓名、性别、年龄四个字段:

create table user_info
(
id int primary key,
age int not null,
name varchar(16),
sex bool
)engine=InnoDB;

向数据库中插入如下数据:

用户ID 1 2 3 4 5 6 7 8 9
姓名 陈尔 张散 李思 王舞 赵流 孙期 周跋 吴酒 郑史
性别
年龄 5 10 20 28 35 56 25 80 90

上述表中插入指定数据后,得到的聚簇索引结构如下所示:

可以看到,聚簇索引的叶子节点包含了所有数据,所以在需要查询某一行数据的所有列时,通过聚簇索引查询的效率最高。

非聚簇索引

InnoDB中,除了聚簇索引以外,其余的索引都可以称为非聚簇索引,非聚簇索引的叶子节点存放主键索引,而不是所有数据。通过非聚簇索引查找数据,其流程是先通过非聚簇索引查找到数据的主键,再通过主键查找对应的数据。

对于上文中的用户表,我们稍微修改一下建表语句,对用户的年龄添加索引:

create table user_info
(
id int primary key,
age int not null,
name varchar(16),
sex bool,
key(age)
)engine=InnoDB;

向表中插入和上文中相同的数据,InnoDB会为这张表生成两个索引树:用户ID对应的聚簇索引树和用户年龄对应的非聚簇索引树,其结构如下图所示。

从图中可以发现,聚簇索引和非聚簇索引最大的区别就是叶子节点存放的内容,聚簇索引的叶子节点存放了数据库一行中的所有数据,而非聚簇索引的叶子节点存放了数据的主键。

大多数情况下,通过非聚簇索引查找到主键值后,还需要通过主键值去聚簇索引查找整行数据,从而获取到满足条件行的所有数据。所以非聚簇索引的查询速度总是会比聚簇索引的查询速度慢一些,日常开发中能使用聚簇索引应该尽量使用聚簇索引。

回表查询

所谓的回表查询,就是指通过非聚簇索引查询数据时,可能需要回到聚簇索引多查询一次数据的情况,对于上文中的数据,执行以下SQL语句,其查询过程如下图中的绿色路径所示。

从图中可以看到,在用户年龄的索引树的叶子节点中,包含了用户的主键ID,由于我们需要获取用户的所有信息,所以还需要按照用户的ID去聚簇索引查找用户的所有信息。

select * from user_info where age = 5;

覆盖索引

如果某次查询的过程中,查询需要的数据在非聚簇索引中就可以得到,那么就没有必要回到聚簇索引查询行所有的数据,这种情况称为覆盖索引。我们可以把上面回表查询的SQL修改为:

select id from user_info where age = 5;

由于年龄索引树的叶子节点就包含了ID信息,所以InnoDB不需要回聚簇索引再次查询用户ID,而是直接将年龄索引树中的ID返回。

本文最先发布至微信公众号,版权所有,禁止转载!

InnoDB学习(八)之 聚簇索引的更多相关文章

  1. Python Tutorial 学习(八)--Errors and Exceptions

    Python Tutorial 学习(八)--Errors and Exceptions恢复 Errors and Exceptions 错误与异常 此前,我们还没有开始着眼于错误信息.不过如果你是一 ...

  2. SVG 学习<八> SVG的路径——path(2)贝塞尔曲线命令、光滑贝塞尔曲线命令

    目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...

  3. InnoDB学习(五)之MVCC多版本并发控制

    MVCC多版本并发控制,是一种数据库管理系统并发控制的方法.MVCC多版本并发控制下,数据库中的数据会有多个版本,分别对应不同的事务,从而达到事务之间并发数据的隔离.MVCC最大的优势是读不加锁,读写 ...

  4. 侯捷STL学习(八)-- 深度探索deque

    layout: post title: 侯捷STL学习(八) date: 2017-07-19 tag: 侯捷STL --- 第十八节 深度探索deque上 duque内存结构 分段连续,用户看起来是 ...

  5. InnoDB学习(一)之BufferPool

    我们知道InnoDB数据库的数据是持久化在磁盘上的,而磁盘的IO速度很慢,如果每次数据库访问都直接访问磁盘,显然严重影响数据库的性能.为了提升数据库的访问性能,InnoDB为数据库的数据增加了内存缓存 ...

  6. InnoDB学习(二)之ChangeBuffer

    ChangeBuffer是InnoDB缓存区的一种特殊的数据结构,当用户执行SQL对非唯一索引进行更改时,如果索引对应的数据页不在缓存中时,InnoDB不会直接加载磁盘数据到缓存数据页中,而是缓存对这 ...

  7. InnoDB学习(四)之RedoLog和UndoLog

    BinLog是MySQL Server层的日志,所有的MySQL存储引擎都支持BinLog.BinLog可以支持主从复制和数据恢复,但是对事务的ACID特性支持比较差.InnoDB存储引擎引入Redo ...

  8. InnoDB学习(七)之索引结构

    索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息.可以将数据库索引和书的目录进行类比,通过书的目录我们可以快速查找到章节位置,如果没有目录就只能一页页翻书查找 ...

  9. Android学习八:获取网络图片

    看到QQ群里有个朋友说加载图片内存溢出的问题,所以就按照自己的想法试试的.但是按照他的方法,不知道为何没有发生内存溢出,不知道什么情况. 写这篇文章主要有三个目的: 1.多线程的学习 2.图片加载的学 ...

随机推荐

  1. 【C/C++】例题5-4 反片语/算法竞赛入门经典/C++与STL入门/映射:map

    本题是映射:map的例题. map:键值对. [题目] 输入一些单词,找出所有满足如下条件的单词:该单词不能通过字母重排,得到输入文本中的另外一个单词. 在判断是否满足条件时,字母不分大小写,但在输出 ...

  2. 全网最详细的AbstractQueuedSynchronizer(AQS)源码剖析(一)AQS基础

    AbstractQueuedSynchronizer(以下简称AQS)的内容确实有点多,博主考虑再三,还是决定把它拆成三期.原因有三,一是放入同一篇博客势必影响阅读体验,而是为了表达对这个伟大基础并发 ...

  3. IT过来人的10点经验谈

    1 入行要趁早,正常是22岁本科或25岁硕士毕业入行.如果是零基础经培训班加持的,尽量在28岁前入行,30岁以后再想要入行IT的,千万慎重. 2 IT行业确实能挣大钱,而且能为学历一般学校一般家庭背景 ...

  4. 如何在子线程中更新UI

    一:报错情况 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that creat ...

  5. 学习整理--vue篇(1)

    vue学习 vue指令 模板指令: v-model:绑定data数据实现数据双向绑定 v-html:绑定模板内容,可书写标签 v-text:绑定数据实现单向绑定 可缩写为{{}} 支持逻辑运算 可结合 ...

  6. Android App加固原理与技术历程

    App为什么会被破解入侵 随着黑客技术的普及化平民化,App,这个承载我们移动数字工作和生活的重要工具,不仅是黑客眼中的肥肉,也获得更多网友的关注.百度一下"App破解"就有529 ...

  7. 【WP】【web】中学生CTF | web部分wp

    $_GET 源码: <?php show_source(__FILE__); include 'config.php'; if(!isset($_GET['args'])){ die(); } ...

  8. 使用CCS10新建TMS320F28335工程并闪烁LED(流水灯)程序

    学习TMS320F28335使用Code Composer Studio 10.4.0下载和安装本文不再叙述. 1. 新建工程 1.1选择目录新建工作区 1.2打开软件界面如下图所示: 1.3选择新建 ...

  9. Table.Range保留中间指定的….Range/Middle(Power Query 之 M 语言)

    数据源: "姓名""基数""个人比例""个人缴纳""公司比例""公司缴纳"&qu ...

  10. CF420A Start Up 题解

    Content 给定一个长度为 \(n\) 的字符串,求这个字符串整个反转过来后是否和原字符串一样. 数据范围:\(1\leqslant n\leqslant 10^5\). Solution 众所周 ...