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. go channel 概述 - 管道

    概述 unix/linux OS 的一个进程的输出可以是另一个进程的输入,这些进程使用stdin与stdout设备作为通道,在进程之间传递数据. 同样的,GO中有io.Reader与io.Writer ...

  2. Default Constructors

    A constructor without any arguments or with default value for every argument, is said to be default ...

  3. 【Java 8】Stream.distinct() 列表去重示例

    在这篇文章里,我们将提供Java8 Stream distinct()示例. distinct()返回由该流的不同元素组成的流.distinct()是Stream接口的方法. distinct()使用 ...

  4. 什么是内容分发CDN

    一.简介 CDN全称:Content Delivery Network或Content Ddistribute Network,即内容分发网络 基本思路: 尽可能避开互联网上有可能影响数据传输速度和稳 ...

  5. LuoguP7285 「EZEC-5」修改数组 题解

    Content 有一个长度为 \(n\) 的 \(0/1\) 串,你可以修改当中的一些元素,求修改后最长的连续为 \(1\) 的子串长度减去修改次数的最大值. 数据范围:\(1\leqslant n\ ...

  6. java IO操作和计算操作:工作内存和主内存 volatile关键字作用;原子操作对象AtomicInteger ....

    应该停止但无法停止的计算线程 如下线程示例,线程实例中while循环中的条件,在主线程中通过调用实例方法更新后,while循环并没有更新判断变量是否还成立.而是陷入了while(true)死循环. i ...

  7. js文件需要jsp页面中的div时,此js文件必须在div之后才能获得值,否则获取不到

    js文件需要jsp页面中的div时,此js文件必须在div之后才能获得值,否则获取不到 2.图2的内容为directionkey.js的内容

  8. JAVA导入(读取)Excel中的数据(支持xls与xlsx文件)

    一.导入jar包 poi-3.7.jarpoi-scratchpad-3.7.jarpoi-examples-3.7.jarpoi-ooxml-3.7.jarpoi-ooxml-schemas-3.7 ...

  9. IDEA设置调用方法时提示方法上的注释

    IDEA设置代码注释提示,代码提示,鼠标放上面提示方法的注解信息 打开file-->setting-->Editor-->General,将Show quick documentat ...

  10. Android 崩溃错误

    SIGSEGV ---段错误. 遇到此错误的可能情况是: 1.缓冲区溢出---通常由指针引用超出范围引起. 2.堆栈溢出---请记住默认堆栈大小为8192K. 3.我们的判断系统禁止文件访问---文件 ...