InnoDB学习(八)之 聚簇索引
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学习(八)之 聚簇索引的更多相关文章
- Python Tutorial 学习(八)--Errors and Exceptions
Python Tutorial 学习(八)--Errors and Exceptions恢复 Errors and Exceptions 错误与异常 此前,我们还没有开始着眼于错误信息.不过如果你是一 ...
- SVG 学习<八> SVG的路径——path(2)贝塞尔曲线命令、光滑贝塞尔曲线命令
目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...
- InnoDB学习(五)之MVCC多版本并发控制
MVCC多版本并发控制,是一种数据库管理系统并发控制的方法.MVCC多版本并发控制下,数据库中的数据会有多个版本,分别对应不同的事务,从而达到事务之间并发数据的隔离.MVCC最大的优势是读不加锁,读写 ...
- 侯捷STL学习(八)-- 深度探索deque
layout: post title: 侯捷STL学习(八) date: 2017-07-19 tag: 侯捷STL --- 第十八节 深度探索deque上 duque内存结构 分段连续,用户看起来是 ...
- InnoDB学习(一)之BufferPool
我们知道InnoDB数据库的数据是持久化在磁盘上的,而磁盘的IO速度很慢,如果每次数据库访问都直接访问磁盘,显然严重影响数据库的性能.为了提升数据库的访问性能,InnoDB为数据库的数据增加了内存缓存 ...
- InnoDB学习(二)之ChangeBuffer
ChangeBuffer是InnoDB缓存区的一种特殊的数据结构,当用户执行SQL对非唯一索引进行更改时,如果索引对应的数据页不在缓存中时,InnoDB不会直接加载磁盘数据到缓存数据页中,而是缓存对这 ...
- InnoDB学习(四)之RedoLog和UndoLog
BinLog是MySQL Server层的日志,所有的MySQL存储引擎都支持BinLog.BinLog可以支持主从复制和数据恢复,但是对事务的ACID特性支持比较差.InnoDB存储引擎引入Redo ...
- InnoDB学习(七)之索引结构
索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息.可以将数据库索引和书的目录进行类比,通过书的目录我们可以快速查找到章节位置,如果没有目录就只能一页页翻书查找 ...
- Android学习八:获取网络图片
看到QQ群里有个朋友说加载图片内存溢出的问题,所以就按照自己的想法试试的.但是按照他的方法,不知道为何没有发生内存溢出,不知道什么情况. 写这篇文章主要有三个目的: 1.多线程的学习 2.图片加载的学 ...
随机推荐
- go channel 概述 - 管道
概述 unix/linux OS 的一个进程的输出可以是另一个进程的输入,这些进程使用stdin与stdout设备作为通道,在进程之间传递数据. 同样的,GO中有io.Reader与io.Writer ...
- Default Constructors
A constructor without any arguments or with default value for every argument, is said to be default ...
- 【Java 8】Stream.distinct() 列表去重示例
在这篇文章里,我们将提供Java8 Stream distinct()示例. distinct()返回由该流的不同元素组成的流.distinct()是Stream接口的方法. distinct()使用 ...
- 什么是内容分发CDN
一.简介 CDN全称:Content Delivery Network或Content Ddistribute Network,即内容分发网络 基本思路: 尽可能避开互联网上有可能影响数据传输速度和稳 ...
- LuoguP7285 「EZEC-5」修改数组 题解
Content 有一个长度为 \(n\) 的 \(0/1\) 串,你可以修改当中的一些元素,求修改后最长的连续为 \(1\) 的子串长度减去修改次数的最大值. 数据范围:\(1\leqslant n\ ...
- java IO操作和计算操作:工作内存和主内存 volatile关键字作用;原子操作对象AtomicInteger ....
应该停止但无法停止的计算线程 如下线程示例,线程实例中while循环中的条件,在主线程中通过调用实例方法更新后,while循环并没有更新判断变量是否还成立.而是陷入了while(true)死循环. i ...
- js文件需要jsp页面中的div时,此js文件必须在div之后才能获得值,否则获取不到
js文件需要jsp页面中的div时,此js文件必须在div之后才能获得值,否则获取不到 2.图2的内容为directionkey.js的内容
- 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 ...
- IDEA设置调用方法时提示方法上的注释
IDEA设置代码注释提示,代码提示,鼠标放上面提示方法的注解信息 打开file-->setting-->Editor-->General,将Show quick documentat ...
- Android 崩溃错误
SIGSEGV ---段错误. 遇到此错误的可能情况是: 1.缓冲区溢出---通常由指针引用超出范围引起. 2.堆栈溢出---请记住默认堆栈大小为8192K. 3.我们的判断系统禁止文件访问---文件 ...