数据库索引,真的越建越好吗?(上)

简介: 索引是提高关系型数据库查询性能的利器,但其并非银弹,必须精通其原理,才能发挥奇效。

索引是提高关系型数据库查询性能的利器,但其并非银弹,必须精通其原理,才能发挥奇效。

InnoDB底层是如何存储数据的?

MySQL把数据存储和查询操作抽象成了存储引擎。MySQL支持多种存储引擎,并且可以以表为粒度设置存储引擎。因为需要事务,所以InnoDB最常用。

为减少磁盘随机读取次数,InnoDB采用页而非行的粒度保存数据,即数据被分成若干页,以页为单位保存在磁盘。InnoDB的页大小默认16K。

  • 各数据页形成双向链表
  • 每个数据页中的记录按主键顺序形成单链表
  • 每一个数据页中有一个页目录,方便按主键查询记录
  • 数据页结构

image.png

页目录通过一个个槽把记录分成不同组。记录中最前面的小矩形数字,代表当前组的记录条数。

最小和最大的槽指向2个特殊的伪记录。

0 =》 最小记录
1 =》 4
2 =》 8
3 =》 12
4 =》 16
5 =》 20
6 =》 最大记录

有了槽,按主键搜索页内记录时,就能用二分查找,而无需从最小记录遍历整个页的记录链表。


比如要搜索主键(PK)=15的记录:

先二分计算得槽中间位(0+6)/2=3,指向记录12<15,所以从槽3后继续搜索

再二分:(3+6)/2=4.5取整4,槽4对应记录16>15,所以记录在槽3

再从槽3指向的12号记录开始向下搜索3次,定位到15号记录

聚簇索引和二级索引

页目录就是最简单的索引,通过对记录进行一级分组来降低搜索的时间复杂度。

这样能够降低的时间复杂度数量级有限。当有无数个数据页来存储表数据时,我们就需要考虑如何建立合适索引,才能方便定位记录所在的页。

为了解决这个问题,InnoDB引入B+树

image.png

  • 最低层的叶子节点,存放数据
  • 其他上层节点-非叶子节点,存放目录项,作为索引
  • 非叶子节点分为不同层次,通过分层降低每层的搜索量
  • 每层节点按索引键大小排序,构成双向链表,加速范围查找

因此,InnoDB使用B+树,既可以保存实际数据,也可加速数据搜索,这就是聚簇索引。


如果把上图叶子节点下面方块中的省略号看作实际数据,那么它就是聚簇索引的示意图。由于数据在物理上只会保存一份,所以包含实际数据的聚簇索引只能有一个。


InnoDB会自动使用主键(唯一定义一条记录的单或多个字段)作为聚簇索引的索引键(若无主键,则选择第一个不包含NULL值的唯一列)。方框数字代表索引键的值,对聚簇索引,一般就是主键。

B+树如何快速查找主键

比如搜索PK=4数据,通过根节点中的索引可知数据在第一个记录指向的2号页,通过2号页的索引又可知道数据在5号页,5号页就是实际数据页,再通过二分查找页目录马上可以找到记录的指针。

为了实现非主键字段的快速搜索,就引出了二级索引,也叫作非聚簇索引、辅助索引。非聚簇索引也是B+树,如下:

image.png

非聚簇索引的叶子节点保存的不是实际数据,而是主键。

获得主键值后去聚簇索引获得数据行,就是回表。


假设该索引是针对用户名字段创建的,索引记录上面方块中的字母是用户名,按顺序形成链表。若要搜索用户名为b的数据,经过两次定位可以得出在数据页5中,查出所有主键为7和6,再拿这俩主键继续使用聚簇索引进行两次回表得到完整数据。

额外创建二级索引的代价

维护代价

创建N个二级索引,就需要再创建N棵B+树,新增数据时不仅要修改聚簇索引,还需要修改这N个二级索引。

假设有如下表:

image.png

通过如下存储过程创建10万条测试数据,约140s。

image.png

再创建两个索引:

image.png

则创建10万条记录的耗时提高到154s。

页中的记录都是按照索引值从小到大的顺序存放的:

  • 新增记录就需要往页中插入数据,现有的页满了就需要新创建一个页,把现有页的部分数据移过去,这就是页分裂
  • 若删除了许多数据使得页很空闲,就需要页合并

页分裂和合并,都会有I/O代价,且过程中可能产生死锁。

空间代价

虽然二级索引不保存原始数据,但要保存索引列的数据,所以会占用更多的空间。

比如,person表创建了两个索引后,使用下面的SQL查看数据和索引占用的磁盘:

SELECT DATA_LENGTH, INDEX_LENGTH FROM information_schema.TABLES 
  WHERE TABLE_NAME='person'

结果显示,数据本身只占用了4.7M,而索引占用了8.4M。

目录
相关文章
|
3月前
|
数据库 索引
深入探索数据库索引技术:回表与索引下推解析
【10月更文挑战第15天】在数据库查询优化的领域中,回表和索引下推是两个核心概念,它们对于提高查询性能至关重要。本文将详细解释这两个术语,并探讨它们在数据库操作中的作用和影响。
85 3
|
3月前
|
数据库 索引
深入理解数据库索引技术:回表与索引下推详解
【10月更文挑战第23天】 在数据库查询性能优化中,索引的使用是提升查询效率的关键。然而,并非所有的索引都能直接加速查询。本文将深入探讨两个重要的数据库索引技术:回表和索引下推,解释它们的概念、工作原理以及对性能的影响。
132 3
|
2月前
|
存储 缓存 数据库
数据库索引采用B+树不采用B树的原因?
B+树优化了数据存储和查询效率,数据仅存于叶子节点,便于区间查询和遍历,磁盘读写成本低,查询效率稳定,特别适合数据库索引及范围查询。
57 6
|
3月前
|
存储 缓存 数据库
数据库索引采用B+树不采用B树的原因
B+树相较于B树,在数据存储、磁盘读写、查询效率及范围查询方面更具优势。数据仅存于叶子节点,便于高效遍历和区间查询;内部节点不含数据,提高缓存命中率;查询路径固定,效率稳定;特别适合数据库索引使用。
53 1
|
3月前
|
数据库 索引
数据库索引
数据库索引 1、索引:建立在表一列或多列的辅助对象,目的是加快访问表的数据。 2、索引的优点: (1)、创建唯一性索引,可以确保数据的唯一性; (2)、大大加快数据检索速度; (3)、加速表与表之间的连接; (4)、在查询过程中,使用优化隐藏器,提高系统性能。 3、索引的缺点: (1)、创建和维护索引需要耗费时间,随数据量增加而增加; (2)、索引占用物理空间; (3)、对表的数据进行增删改时,索引需要动态维护,降低了数据的维护速度。
54 2
|
4月前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
97 3
Mysql(4)—数据库索引
|
3月前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
585 1
|
3月前
|
存储 关系型数据库 数据库
Postgres数据库BRIN索引介绍
BRIN索引是PostgreSQL提供的一种高效、轻量级的索引类型,特别适用于大规模、顺序数据的范围查询。通过存储数据块的摘要信息,BRIN索引在降低存储和维护成本的同时,提供了良好的查询性能。然而,其适用场景有限,不适合随机数据分布或频繁更新的场景。在选择索引类型时,需根据数据特性和查询需求进行权衡。希望本文对你理解和使用PostgreSQL的BRIN索引有所帮助。
108 0
|
3月前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
377 0
|
4月前
|
关系型数据库 MySQL 数据库
深入浅出MySQL索引优化:提升数据库性能的关键
在这个数据驱动的时代,数据库性能的优劣直接关系到应用的响应速度和用户体验。MySQL作为广泛使用的数据库之一,其索引优化是提升查询性能的关键。本文将带你一探MySQL索引的内部机制,分析索引的类型及其适用场景,并通过实际案例演示如何诊断和优化索引,以实现数据库性能的飞跃。

热门文章

最新文章