索引原理

MySQL官方对索引定义:是存储引擎用于快速查找记录的一种数据结构。需要额外开辟空间和数据维护 工作。

  • 索引是物理数据页存储,在数据文件中(InnoDB,ibd文件),利用数据页(page)存储。
  • 索引可以加快检索速度,但是同时也会降低增删改操作速度,索引维护需要代价。

索引涉及的理论知识:二分查找法、Hash和B+Tree。

二分查找法

二分查找法也叫作折半查找法,它是在有序数组中查找指定数据的搜索算法。它的优点是等值查询、范 围查询性能优秀,缺点是更新数据、新增数据、删除数据维护成本高。

  • 首先定位left和right两个指针
  • 计算(left+right)/2
  • 判断除2后索引位置值与目标值的大小比对
  • 索引位置值大于目标值就-1,right移动;如果小于目标值就+1,left移动

举个例子,下面的有序数组有17 个值,查找的目标值是7,过程如下:

  • 第一次查找  
  • 第二次查找
  • 第三次查找
  • 第四次查找

Hash结构 

Hash底层实现是由Hash表来实现的,是根据键值 存储数据的结构。非常适合根据key查找 value值,也就是单个key查询,或者说等值查询。其结构如下所示:

mysql索引的设计原则 mysql索引的原理_聚簇索引

从上面结构可以看出,Hash索引可以方便的提供等值查询,但是对于范围查询就需要全表扫描了。 Hash索引在MySQL 中Hash结构主要应用在Memory原生的Hash索引 、InnoDB 自适应哈希索引。

InnoDB提供的自适应哈希索引功能强大,接下来重点描述下InnoDB 自适应哈希索引。

InnoDB自适应哈希索引是为了提升查询效率,InnoDB存储引擎会监控表上各个索引页的查询,当 InnoDB注意到某些索引值访问非常频繁时,会在内存中基于B+Tree索引再创建一个哈希索引,使得内 存中的 B+Tree 索引具备哈希索引的功能,即能够快速定值访问频繁访问的索引页。

InnoDB自适应哈希索引:在使用Hash索引访问时,一次性查找就能定位数据,等值查询效率要优于 B+Tree。

自适应哈希索引的建立使得InnoDB存储引擎能自动根据索引页访问的频率和模式自动地为某些热点页 建立哈希索引来加速访问。另外InnoDB自适应哈希索引的功能,用户只能选择开启或关闭功能,无法 进行人工干涉。

show engine innodb status \G;
show variables like '%innodb_adaptive%';

B+Tree结构

MySQL数据库索引采用的是B+Tree结构,在B-Tree结构上做了优化改造。

  • B-Tree结构
    索引值和data数据分布在整棵树结构中
    每个节点可以存放多个索引值及对应的data数据
    树节点中的多个索引值从左到右升序排列

    B树的搜索:从根节点开始,对节点内的索引值序列采用二分法查找,如果命中就结束查找。没有 命中会进入子节点重复查找过程,直到所对应的的节点指针为空,或已经是叶子节点了才结束。
  • B+Tree结构
    非叶子节点不存储data数据,只存储索引值,这样便于存储更多的索引值
    叶子节点包含了所有的索引值和data数据
    叶子节点用指针连接,提高区间的访问性能

    相比B树,B+树进行范围查找时,只需要查找定位两个节点的索引值,然后利用叶子节点的指针进 行遍历即可。而B树需要遍历范围内所有的节点和数据,显然B+Tree效率高。

聚簇索引和辅助索引 

聚簇索引和非聚簇索引:B+Tree的叶子节点存放主键索引值和行记录就属于聚簇索引;如果索引值和行 记录分开存放就属于非聚簇索引。

主键索引和辅助索引:B+Tree的叶子节点存放的是主键字段值就属于主键索引;如果存放的是非主键值 就属于辅助索引(二级索引)。

在InnoDB引擎中,主键索引采用的就是聚簇索引结构存储。

  • 聚簇索引(聚集索引)
    聚簇索引是一种数据存储方式,InnoDB的聚簇索引就是按照主键顺序构建 B+Tree结构。B+Tree 的叶子节点就是行记录,行记录和主键值紧凑地存储在一起。 这也意味着 InnoDB 的主键索引就 是数据表本身,它按主键顺序存放了整张表的数据,占用的空间就是整个表数据量的大小。通常说 的主键索引就是聚集索引。
    InnoDB的表要求必须要有聚簇索引:
         1.如果表定义了主键,则主键索引就是聚簇索引
         2.如果表没有定义主键,则第一个非空unique列作为聚簇索引
         3.否则InnoDB会从建一个隐藏的row-id作为聚簇索引
  • 辅助索引
    InnoDB辅助索引,也叫作二级索引,是根据索引列构建 B+Tree结构。但在 B+Tree 的叶子节点中 只存了索引列和主键的信息。二级索引占用的空间会比聚簇索引小很多, 通常创建辅助索引就是 为了提升查询效率。一个表InnoDB只能创建一个聚簇索引,但可以创建多个辅助索引。
  • 非聚簇索引
    与InnoDB表存储不同,MyISAM数据表的索引文件和数据文件是分开的,被称为非聚簇索引结 构。