目录

1. 索引及其优缺点

1.1 索引概述

1.2 优点

1.3 缺点

2. 索引的数据结构:B+树

3. 常见索引概念

3.1  聚簇索引

特点:

优点:

缺点:

3.2 二级索引(辅助索引、非聚簇索引)

3.3 联合索引

4. 索引的代价

4.1 空间上的代价

4.2 时间上的代价


1. 索引及其优缺点

 

1.1 索引概述

MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构

索引的本质:索引是数据结构。你可以简单理解为“排好序的快速查找数据结构”,满足特定查找算法。这些数据结构以某种方式指向数据, 这样就可以在这些数据结构的基础上实现高级查找算法

1.2 优点

(1)类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本,这也是创建索引最主要的原因。

(2)通过创建唯一索引,可以保证数据库表中每一行数据的唯一性

(3)在实现数据的参考完整性方面,可以加速表和表之间的连接。换句话说,对于有依赖关系的子表和父表联合查询时,可以提高查询速度。

(4)在使用分组和排序子句进行数据查询时,可以显著减少查询中分组和排序的时间,降低了CPU的消耗。

1.3 缺点

(1)创建索引和维护索引要耗费时间,并且随着数据量的增加,所耗费的时间也会增加

(2)索引需要占磁盘空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间存储在磁盘上,如果有大量的索引,索引文件就可能比数据文件更快达到最大文件尺寸。

(3)虽然索引大大提高了查询速度,同时却会降低更新表的速度。当对表中的数据进行增加、删除和修改的时候,索引也要动态地维护,这样就降低了数据的维护速度。


2. 索引的数据结构:B+树

这里对于索引的数据结构不多说,接下来我会单独写关于B+树的文章。

推荐一个网站可以查看B+树构造的过程:Data Structure Visualization

简版B+树

 

 

  • 叶子节点存储完整数据
  • 页内单向链表
  • 页间双向链表
  • 目录项双向链表
  • 根节点常驻内存
  • 三层的B+树就可以存储千万条记录,并且查询效率稳定
  • 支持范围查找

3. 常见索引概念

 

3.1  聚簇索引

特点:

1.页内的记录是按照主键的大小顺序排成一个单向链表。

2.各个存放用户记录的也是根据页中用户记录的主键大小顺序排成一个双向链表

3.存放目录项记录的页分为不同的层次,在同一层次中的页也是根据页中目录项记录的主键大小顺序排成一个双向链表

4.B+树的叶子节点存储的是完整的用户记录。所谓完整的用户记录,就是指这个记录中存储了所有列的值(包括隐藏列)。

5.nnoDB要求表必须有主键。如果没有显式指定,则MySQL系统会自动选择一个可以非空且唯一标识数据记录的列作为主键。

如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整型。

优点:

数据访问更快,因为聚簇索引将索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比非聚簇索引更快

聚簇索引对于主键的排序查找和范围查找速度非常快

按照聚簇索引排列顺序,查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不用从多个数据块中提取数据,所以节省了大量的io操作。

缺点:

插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。

因此,对于InnoDB表,我们一般都会定义一个自增ID列为主键

更新主键的代价很高,因为将会导致被更新的行移动。

因此,对于InnoDB表,我们一般定义主键为不可更新 二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据


3.2 二级索引(辅助索引、非聚簇索引)

采用Innodb存储引擎的表中,除了主键索引(聚簇索引),其他都是二级索引(非聚簇索引)

主键索引是InnoDB存储引擎默认给我们创建的一套索引结构,我们表里的数据也是直接放在主键索引里,作为叶子节点的数据页。

但我们在开发的过程中,往往会根据业务需要在不同的字段上建立索引,这些索引就是二级索引。

二级索引目录项如何确保唯一

我们把索引值以及主键值都添加到了二级索引节点的目录项中


3.3 联合索引


我们也可以同时以多个列的大小作为排序规则,也就是同时为多个列建立索引,比方说我们想让B+树按照name和age列的大小进行排序,这个包含两层含义:


先把各个记录和页按照name列进行排序。

在记录的name列相同的情况下,采用age列进行排序

注意一点,以name和age列的大小为排序规则建立的B+树称为联合索引,本质上也是一个二级索引。它的意思与分别为name和age列分别建立索引的表述是不同的。

不同点如下:

建立联合索引只会建立如上图一样的1棵B+树。

为name和age列分别建立索引会分别以name和age列的大小为排序规则建立2棵B+树。

建立一个联合索引的效率的远大于两个单列索引,并且维护成本还低。


4. 索引的代价

索引是个好东西,可不能乱建,它在空间和时间上都会有消耗:

4.1 空间上的代价

每建立一个索引都要为它建立一棵B+树,每一棵B+树的每一个节点都是一个数据页,一个页默认会占用16KB的存储空间,一棵很大的B+树由许多数据页组成,那就是很大的一片存储空间。

4.2 时间上的代价

每次对表中的数据进行增、删、改操作时,都需要去修改各个B+树索引。

B+树每层节点都是按照索引列的值从小到大的顺序排序而组成了双向链表。

不论是叶子节点中的记录,还是内节点中的记录(也就是不论是用户记录还是目录项记录)都是按照索引列的值从小到大的顺序而形成了一个单向链表。

增、删、改操作可能会对节点和记录的排序造成破坏,所以存储引擎需要额外的时间进行一些记录移位,页面分裂、页面回收等操作来维护好节点和记录的排序。

如果我们建了许多索引,每个索引对应的B+树都要进行相关的维护操作,会给性能拖后腿。

下一篇文章我来说索引的优化,那些列适合创建索引,那些列不适合创建索引,并且索引失效的原因。

如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏

Logo

本社区面向用户介绍CSDN开发云部门内部产品使用和产品迭代功能,产品功能迭代和产品建议更透明和便捷

更多推荐