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. springboot热部署与监控

    一.热部署 添加依赖+Ctrl+F9 <dependency> <groupId>org.springframework.boot</groupId> <ar ...

  2. Java Timestamp 类的使用

    很简单,我们可以这样声明 Timestamp ts=new Timestamp(new Date().getTime());这样我们就可以得到时间比较具体的一个类型转换!!! 在开发web应用中,针对 ...

  3. 学习Oracle遇到的实际问题(持续更新)

    有三个用户参与这个事情: system用户,拥有表manager. sys create了一个用户item,并赋予权限: SQL> GRANT SELECT ON SYSTEM.MANAGER ...

  4. ts配置项

    { "compilerOptions": { /* 基本选项 */ "target": "es5", // 指定 ECMAScript 目标 ...

  5. LuoguP7715 「EZEC-10」Shape 题解

    Content 有一个 \(n\times m\) 的网格,网格上的格子被涂成了白色或者黑色. 设两个点 \((x_1,y_1)\) 和 \((x_2,y_2)\),如果以下三个条件均满足: \(1\ ...

  6. CF1514A Perfectly Imperfect Array 题解

    Content 给定一个长度为 \(n\) 的序列,问是否存在一个非空子序列,使得这个子序列所有元素的积不是完全平方数. 数据范围:\(t\) 组数据,\(1\leqslant t\leqslant ...

  7. SpringBoot整合MQTT (使用官方demo)

    依赖 <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse. ...

  8. Linux(centos)使用shell脚本停止启动jar包

    在jar包目录下创建一个文件,后缀为 .sh #!/bin/bash # stop service pid=`ps -ef | grep "jar包名字" | grep -v &q ...

  9. Linux(Centos)内存占用过高处理

    查看内存占用最大 ps aux| grep -v "USER" |sort -n -r -k 4 |awk 'NR==1{ print $0}' 命令查看占用内存最大的10个进程 ...

  10. 百度地图AK密钥申请

    注册登录 :http://lbsyun.baidu.com/apiconsole/key#/home 然后点击提交 这个就是AK密钥