0201概述和结构-索引-MySQL

文章目录

    • 1 概述
      • 1.1 介绍
      • 1.2 优缺点
    • 2 索引结构
      • 2.1 B+Tree索引
      • 2.2 hash索引
      • 2.3 对比
    • 3 索引分类
      • 3.1 通用分类
      • 3.2 InnoDB存储引擎分类
    • 4 思考题
    • 后记

1 概述

1.1 介绍

索引是帮忙MySQL 高效获取数据的数据结构(有序)。在数据之外,数据系统还维护着满足特定查找算法的数据结构。这些数据结构以某种方式音乐(指向)数据,这样就可以在这些数据结构傻姑娘实现高级查找算法,这种数据结构就是索引。

1.2 优缺点

优势 缺点
提高数据检索的效率,将低数据IO成本 索引列需要占有空间
通过索引列对数据进行排序,将低数据排序的成本,将低CPU的消耗 索引大大提高查询效率,在更新的时候需要维护索引,效率降低

2 索引结构

MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的索引结构,按照存储结构分类主要包含以下几种:

索引结构 描述
B+Tree索引 最常见的索引类型,大部分引擎都支持B+树索引
Hash索引 底层数据结构是用哈希表实现的,只有精确匹配索引列的查询才有效,不支持范围查询
R-tree(空间索引) 空间索引是MYISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少
Full-text(全文索引) 是一种通过建立倒排索引,快速匹配文档的方式。类似于Lucene,Solr,ES

2.1 B+Tree索引

B+树(B+tree)是一种常用的平衡树数据结构,也是MySQL中常用的索引结构之一,用于提高数据访问效率。B+树与B树类似,但有着更高的磁盘块利用率和更好的查询性能。

B+树的特点如下:

  1. 所有关键字都出现在叶子结点的链表中,且链表中的关键字恰好是按照大小顺序排列的。
  2. 所有非叶子结点可看成是索引部分,结点中仅含有其子树根结点中的最大(或最小)关键字。
  3. 每个叶子结点都带有指向其后继结点的指针,加速区间访问或遍历。

相对于B树,B+树的区别在于:

  1. 非叶子结点仅仅是索引,不存储数据。
  2. 所有数据都存储在叶子结点中。
  3. 叶子结点之间都有指针相连,可以轻易地进行区间查找或遍历。

B+树通常应用于磁盘上的存储,因为它能够更好地利用磁盘块,减少了磁盘I/O操作的次数。当数据量较大时,B+树能够更快地查询到数据。

在MySQL中,使用B+树索引结构的表通常有一个叶子节点包含所有数据的指针,以及多个索引节点来加速查找。这些索引节点仅仅是用来定位叶子节点的位置,不存储具体的数据。B+树索引可以提高查询性能,特别是对于范围查询等操作,但对于大量的更新操作,B+树索引会比较慢,因为更新数据时需要不断地调整索引结构。

如下图2.1-1所示:

0201概述和结构-索引-MySQL_第1张图片

B+树一个节点对应一页/块,页为InnoDB引擎逻辑存储结构中固定大小的存储结构。每个非叶子结点不用存储数据,可以存储更多的key,同样数据量大情况下,树的高度自然更低,查询效率相应更高。

InnoDB引擎逻辑存储结构,如下图2.1-2所示:

0201概述和结构-索引-MySQL_第2张图片

2.2 hash索引

哈希索引(hash index)基于哈希表实现。哈希索引通过Hash算法(直接定址法、平方取中法、折叠法、除数取余法、随机数法)将数据库的索引列数据转换成定长的哈希码作为key,将这条数据的行的地址作为value一并存入Hash表的对应位置。

在MySQL中,只有Memeory引擎显式的支持哈希索引,这也是Memory引擎表的默认索引结构,Memeory同时也支持B-Tree索引。并且,Memory引擎支持非唯一哈希索引,如果多个列的哈希值相同(或者发生了Hash碰撞),索引会在对应Hash键下以链表形式存储多个记录地址。

Hash索引的特点:

  • Hash索引只用于对等比较(=,in),不支持范围查询(between,>,<,…);
  • 无法利用索引完成排序操作;
  • 查询效率高,通常只需要一次检索就可以了。

存储引擎支持:

在MySQL重,支持hash索引的是Memory引擎,而Inno DB中具有自适应hash功能,hash索引是存储引擎根据B+Tree索引在指定条件下自动构建的。

2.3 对比

问题1:为什么Inno DB存储引擎选择使用B+Tree索引结构?

  • B+Tree,相对于二叉树,层数少,搜索效率高。
  • 相比于B-Tree非叶子结点不存储数据,每个结点(页)能够存储更多的键,那么相同数据量大情况下层级更低,效率更高;
  • 相比于Hash,它支持范围查询。

3 索引分类

3.1 通用分类

主要分类如下表3-1所示:

分类 含义 特点 关键字
主键索引 针对于表中主键创建的索引 默认自动创建,只能由一个 PRIMARY
唯一索引 限制同一表中某数据列值不能重复 可以有多个 UNIQUE
常规索引 快速定位特定数据 可以有多个
全文索引 全文索引查找的是文本中的关键词,而不是比较索引中的值 可以有多个 FULLTEXt
  1. 主键索引(Primary Key Index):主键是一种用于唯一标识每个记录的索引,通常使用B+树作为索引结构,可以快速定位到指定的记录。主键索引在查询、更新、删除等操作时具有高效性能。
  2. 唯一索引(Unique Index):唯一索引要求索引列的值不能重复,通常用于保证数据的唯一性和数据完整性。唯一索引通常也使用B+树作为索引结构,与主键索引类似。
  3. 普通索引(Normal Index):普通索引是最基本的索引类型,它可以加速查询特定列或多个列的值。普通索引也常使用B+树作为索引结构。
  4. 全文索引(Full-Text Index):全文索引可以用于高效地进行文本匹配和搜索。它不像普通索引只能匹配关键字的前缀,而是能够匹配关键字的任意位置。全文索引通常采用特殊的数据结构,如倒排索引等。

需要根据具体场景和查询需求来选择合适的索引类型。选择适当的索引类型可以有效地提高数据库的查询效率和性能

3.2 InnoDB存储引擎分类

InnoDB存储引擎中,根据所有的存储形式,又可以分为以下两种:

分类 含义 特点
聚集索引 将数据存储和索引放在一起,索引结构的叶子结点保存了行数据 必须有,而且只有一个
二级索引 将数据和索引分开存储,索引结构的叶子结点关联的是对应的主键 可以存在多个

聚集索引选取规则:

  • 如果存在主键,主键索引就是聚集索引;
  • 如果不存在主键,将使用第一个唯一索引作为聚集索引;
  • 如果表没有主键或者没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引。

示例表及结构如下图3.2-1所示:

0201概述和结构-索引-MySQL_第3张图片

  • 聚集索引为主键索引,叶解决存储主键对应行数据;
  • name字段建立的索引为二级索引,叶结点存储主键。

接下来我们该SQL语句select * from user where name='Arm'的执行过程,如下图3.2-2所示:

0201概述和结构-索引-MySQL_第4张图片

具体过程如下:

  • 根据name字段查找,先根据name=‘Arm’到name字段到二级索引进行匹配查找,查找结果为对应的主键10;
  • 在根据主键id=10在id字段的聚集索引(主键索引)匹配查找,找到对应的行记录row。

回表查询:先在二级索引中查找数据,找到主键。然后在到聚集索引中根据主键获取数据的方式,称为回表查询。

4 思考题

示例表同#3中user表

  1. 以下2条SQL语句那个执行效率高?为什么
select * from user where id=10;
select * from user where name='Arm';
-- id为主键,name字段创建有索引

回答:第一条SQL语句执行效率高;

解析:

  • 第一条查询字段id为主键,通过聚集索引根据主键匹配查询相应的数据行;而第二条查询根据name字段,需要先通过二级索引查询出主键,在通过聚集索引根据id(主键字段)查询对应数据。
  1. InnoDB的主键索引B+tree指定高度可以存储多少条记录?

B+tree存储结构如下图4-1所示所示:

0201概述和结构-索引-MySQL_第5张图片

假设: 一行数据大小为1k,一页中可以存储16行这样的数据。InnoDB的指针占用6个字节的空

间,假设主键即使为bigint,占用字节数为8。 高度为2:

n ∗ 8 + ( n + 1 ) ∗ 6 = 16 ∗ 1024 , 算出 n 约为 1170 ; 1171 ∗ 16 = 18736 n*8+(n+1)*6=16*1024, 算出n约为 1170; 1171* 16 = 18736 n8+(n+1)6=161024,算出n约为1170;117116=18736 也就是说,如果树的高度为2,则可以存储 18000 多条记录。

高度为3:
1171 * 1171 * 16 = 21939856 也就是说,如果树的高度为3,则可以存储 2200w 左右的记录。

一行数据大小为rowSize,一页大小为16k,InnoDB的指针占有6字节大小,主键类型占有大小为primarySize,高度为h,则存储记录公式为:

  • 非叶结点计算主键数量: k e y s ∗ p r i m a r y S i z e + ( k e y s + 1 ) ∗ 6 = 16 ∗ 1024 keys*primarySize+(keys+1)*6=16*1024 keysprimarySize+(keys+1)6=161024

  • 叶结点计算可以存储多少记录: k e y s h − 1 ⋅ 16 ∗ 1024 r o w S i z e = r e c o r d s \quad keys^{h-1}\cdot\frac{16*1024}{rowSize}=records keysh1rowSize161024=records

  • 大小单位为字节,keys为主键数量。

后记

如果小伙伴什么问题或者指教,欢迎交流。

❓QQ:806797785

参考链接:

[1]ChatGPT

[2]MySQL数据库视频[CP/OL].2020-04-16.p66-73.

[3]MySQL相关(番外篇)- innodb 逻辑存储结构.[CP/OL].

[4]MySQL之InnoDB存储引擎-逻辑存储结构.[CP/OL].

你可能感兴趣的:(#,MySQL,索引,MySQL,B+tree)