问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

高效数据库设计:InnoDB索引的最佳实践与B+树详解

创作时间:
作者:
@小白创作中心

高效数据库设计:InnoDB索引的最佳实践与B+树详解

引用
1
来源
1.
https://www.cnblogs.com/wys777/p/18763144

在数据库管理系统中,索引是一种数据结构,它能够显著加快数据库表中数据的检索速度。对于MySQL的InnoDB存储引擎而言,索引不仅提高了查询效率,还支持事务处理、外键约束等高级功能。通过为数据库中的一个或多个列创建索引,用户可以大大减少查询所需的时间,尤其是在处理大规模数据集时。索引的工作原理类似于书籍的目录,使得查找特定信息变得更加高效和快捷。

InnoDB索引结构

为什么不选择Hash?

Hash索引通过哈希函数将键值映射到特定的桶(bucket),适用于精确匹配查询。然而,Hash索引的主要缺点是它不支持范围查询和排序操作。例如,当我们需要执行类似SELECT * FROM table WHERE column BETWEEN value1 AND value2这样的查询时,Hash索引无法有效地处理这种需求。因此,尽管Hash索引在某些场景下可以提供非常快速的等值查询,但由于其对范围查询的支持有限,InnoDB并未选择它作为主要的索引结构。

B树与B+树的结构

B树

B树是一种自平衡的多路查找树,每个节点可以包含多个键值和子节点指针。在B树中,节点不仅存储索引值,还存储实际的行数据。假设MySQL以页来存储数据,一页大小为16KB,而索引值大约占用8字节,数据记录大约占用1KB。那么,一个节点可以存储的数据量计算如下:

  • 每个节点的总大小:16 * 1024 / (8 + 1024) ≈ 15(取整)
  • 第一层:存储15个数据
  • 第二层:存储 15 * 15 = 225 个数据
  • 第三层:存储 15 * 15 * 15 = 3,375 个数据

以此类推,随着数据量的增加,树的高度也会不断增加。较高的树意味着更多的磁盘I/O操作,这会显著降低查询效率。

B+树

与B树不同,B+树的非叶子节点仅存储索引值和指向下一个索引值的指针,而不存储实际的数据记录。具体来说:

  • 索引值大小:8字节
  • 指针大小:6字节
  • 总共:8 + 6 = 14 字节

在一个16KB的页中,可以存储的索引项数量为:

  • 16 * 1024 / 14 ≈ 1170(取整)

因此,B+树的结构如下:

  • 第一层:存储1170个索引项
  • 第二层:存储 1170 * 1170 ≈ 1,368,900 个索引项
  • 第三层(叶子节点):每页存储的实际数据记录数为 16 * 1024 / 1032 ≈ 15(取整)

这样,三层B+树可以存储的数据总量为:

  • 1170 * 1170 * 15 ≈ 20,000,000 条记录

此外,B+树的叶子节点之间通过双向链表相连,这大大提升了区间访问的效率。

为什么选择B+树?

B+树之所以被InnoDB选为主要的索引结构,原因在于以下几个方面:

  • 更高的节点利用率:由于B+树的非叶子节点只存储索引值和指针,每个节点可以容纳更多的键值,从而减少了树的高度。较低的树高度意味着更少的磁盘I/O操作,提高了查询效率。
  • 支持范围查询和排序:B+树的叶子节点通过双向链表相连,使得范围查询变得非常高效。无论是顺序扫描还是范围查询,都可以通过遍历叶子节点链表快速完成。
  • 高并发支持:B+树结构非常适合并发环境下的读写操作。InnoDB通过锁定机制和事务管理,确保了在高并发环境下数据的一致性和完整性。
  • 查询时间稳定:B+树的低层级结构使得查询时间更加稳定和高效,无论数据量如何增长,都能保证相对较少的磁盘I/O操作次数,从而实现更快的查询响应时间。因此,B+树成为InnoDB索引机制的核心选择。

索引分类

聚簇(集)索引

聚簇索引选取规则:

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

定义与特点

聚簇索引(Clustered Index)是数据库中的一种索引类型,它决定了表中数据的物理存储顺序。在InnoDB存储引擎中,聚簇索引通常是主键索引。具体来说:

  • 定义:聚簇索引通过主键对数据行进行排序并存储。这意味着数据行的实际存储顺序与聚簇索引的键值顺序一致。
  • 特点:
  • 每个表只能有一个聚簇索引,因为数据行只能按一种顺序进行物理存储。
  • 聚簇索引通常用于频繁查询的字段,因为它能够显著提高查询效率。
  • 使用B+树结构,叶子节点存储完整的数据行,包括所有列的数据。由于数据行按主键顺序存储,因此相邻的叶子节点通常也存储相邻的主键值。

非聚簇(集)索引

定义与特点

非聚簇索引(Non-Clustered Index)是除主键之外的其他索引类型,它们不影响数据的物理存储顺序。具体来说:

  • 定义:非聚簇索引存储的是索引键值及其对应的主键值或行位置信息。当查询通过非聚簇索引找到所需记录时,还需要通过主键或其他方式访问实际数据行。
  • 特点:
  • 一个表可以有多个非聚簇索引,适用于辅助查询优化。
  • 非聚簇索引同样使用B+树结构,但它们指向的是聚簇索引中的记录。

InnoDB索引类型详解

主键索引

针对于表中主键创建的索引

定义与特点:

  • 定义:主键索引用于唯一标识每一行记录,并决定了数据的物理存储顺序。
  • 特点:
  • 每个表只能有一个主键索引
  • 非叶子节点存储主键值,而叶子节点存储完整的行数据。因此,通过主键可以直接在索引树上找到数据,不需要额外的表查找操作,查询速度非常快。

最佳实践:

  • 推荐使用自增主键,自增主键(如AUTO_INCREMENT)确保插入的数据始终会被追加到索引树的末尾,这样可以快速找到插入位置,无需进行额外的操作如移动数据或旋转树结构。如果主键不是自增的,数据库无法确定插入的具体位置,可能需要进行额外的操作来维护索引树的平衡,这会导致不必要的开销。
  • 创建主键的列建议是没有业务意义的列,以避免业务逻辑变化对数据库结构的影响。

非主键索引

普通索引

普通索引是最基本的索引类型,不限制列值的唯一性,主要用于加快查询速度。

特点:

  • 非叶子节点存储索引列值。
  • 叶子节点存储的是主键值,而不是实际的数据行。
  • 这种设计使得在通过普通索引查询时,首先找到主键值,然后通过主键索引获取完整的行数据。

唯一索引

唯一索引用于确保索引列中的所有值都是唯一的(允许NULL值),主要用于防止重复数据,增强数据完整性。

特点:

  • 适用于需要保证数据唯一性的场景,如用户表中的邮箱字段。

联合索引

联合索引(也称为组合索引)是指在多个列上创建的索引,通常用于优化特定查询条件下的性能。

特点:

  • 表示为多个列的组合索引,例如在一个表中有id、name、age和phone列,可以创建一个联合索引name, age, phone。
  • 联合索引可以显著提高某些查询条件下的性能,特别是当查询条件涉及到多个列时。

全文索引

全文索引是一种专门用于文本搜索的索引类型,支持复杂的文本匹配逻辑,适用于大文本字段。

特点:

  • 适用于大文本字段,如文章内容、产品描述等。
  • 支持模糊查询、短语查询等多种高级搜索功能。
  • 对于大规模文本数据的搜索,InnoDB的全文索引虽然有效,但在某些情况下,使用专门的搜索引擎如Elasticsearch可能会更加高效。

为什么非主键索引的叶子节点存储的是主键值?

如果不存储主键值,而是直接存储数据,那么当数据发生变化时,不仅需要维护主键索引,还需要同步更新其他索引。这种做法会导致额外的开销和复杂的维护工作。通过存储主键值,可以简化索引的维护过程。

创建索引的要求

  • 单表索引不超过5个
  • 联合索引的字段不超过5个
  • 经常增删改的字段不适合创建索引
  • 枚举值字段不适合创建索引
  • 不经常修改,经常查询的字段适合创建索引
  • 大长度的字段,可以设置前缀索引(为字段的前几个字符建立索引)
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号