当前位置: 首页 > article >正文

MySQL 之索引详解

想象一下,你正在图书馆寻找一本关于 MySQL 索引的书。图书馆里有成千上万本书,但没有目录。你只能一排一排、一本一本地找,直到找到你想要的书。这将会花费大量的时间!数据库索引就像图书馆的目录一样,可以帮助数据库系统快速定位到所需数据,从而大大提高查询速度。

1. 索引基础:概念与类型

1.1 什么是索引?

索引是一种特殊的数据结构,它存储了表中一列或多列的值以及对应行的物理地址。当数据库执行查询时,会首先在索引中查找符合条件的记录地址,然后再根据地址直接访问数据行,从而避免了全表扫描,提高了查询效率。

示例:

假设我们有一个名为 users 的表,包含以下数据:

idnameemail
1张三zhangsan@example.com
2李四lisi@example.com
3王五wangwu@example.com

如果我们在 name 列上创建索引,数据库就会创建一个索引结构,其中包含 name 列的值和对应行的 id:

nameid
张三1
李四2
王五3

当我们执行查询 SELECT * FROM users WHERE name = '李四' 时,数据库会首先在索引中找到 name 为 '李四' 的记录,然后直接访问 id 为 2 的行,而不需要扫描整个 users 表。

1.2 常见的索引类型

MySQL 支持多种类型的索引,常见的包括:

  • 主键索引 (PRIMARY KEY): 唯一标识表中每一行的索引,一个表只能有一个主键索引,主键索引的值不能为空。

  • 唯一索引 (UNIQUE): 唯一索引保证索引列的值是唯一的,可以有多个唯一索引,允许为空值(但只允许一个空值)。

  • 普通索引 (INDEX): 最基本的索引类型,没有任何限制,用于加速查询速度。

  • 全文索引 (FULLTEXT): 用于在文本字段中进行全文搜索,主要用于 MyISAM 引擎。

2. 索引的利与弊

优点:

  • 大大加快数据的检索速度,这是创建索引的最主要原因。

  • 加速表之间的连接,特别是在实现数据的参考完整性方面特别有用。

  • 在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间。

缺点:

  • 创建和维护索引需要耗费时间,而且随着数据量的增加而增加。

  • 索引需要占用物理空间,如果要建立索引的列数据量很大,那么需要的存储空间也会很大。

  • 当对表中的数据进行修改时,比如添加、删除和修改,索引也需要动态地维护,降低了数据的维护速度。

3. 索引操作:创建与删除

创建索引:

可以使用 CREATE INDEX 或 ALTER TABLE 语句来创建索引:

  • CREATE INDEX:

CREATE INDEX index_name ON table_name (column_name);

示例:

CREATE INDEX idx_name ON users (name);
  • ALTER TABLE:

ALTER TABLE table_name ADD INDEX index_name (column_name);

示例:

ALTER TABLE users ADD INDEX idx_email (email);

删除索引:

可以使用 DROP INDEX 或 ALTER TABLE 语句来删除索引:

  • DROP INDEX:

DROP INDEX index_name ON table_name;

示例:

DROP INDEX idx_name ON users;
  • ALTER TABLE:

ALTER TABLE table_name DROP INDEX index_name;

示例:

ALTER TABLE users DROP INDEX idx_email;

4. 深入底层:数据结构与性能对比

前面我们已经了解了索引的基本概念,现在让我们更深入地探讨 MySQL 索引的底层实现原理,以及使用索引和不使用索引在性能上的巨大差异。

4.1 索引的数据结构

MySQL 索引的底层数据结构主要有两种:B+Tree(多路平衡搜索树) 和 哈希表。我们平常所说的索引,如果没有特别指明,都是指默认的 B+Tree 结构组织的索引。

  • B+ 树 是一种多路平衡查找树,它将所有数据存储在叶子节点,非叶子节点只存储索引值和指向子节点的指针。所有叶子节点通过链表连接,方便范围查询,并且每个节点可以存储多个索引值,降低树的高度,减少 I/O 次数, 使其成为 MySQL 索引最常用的数据结构。

  • 哈希表 是一种键值对存储结构,它通过哈希函数将索引值映射到哈希表中的一个位置,从而实现快速查找。哈希表适用于等值查询,例如 WHERE name = '张三',但不适用于范围查询。MySQL 中,Memory 存储引擎默认使用哈希索引,而 InnoDB 存储引擎默认使用 B+ 树索引。

B + Tree(多路平衡搜索树)结构介绍,如图所示:

B+Tree结构:

  • 每一个节点,可以存储多个key(有n个key,就有n个指针)

  • 节点分为:叶子节点、非叶子节点

    • 叶子节点,就是最后一层子节点,所有的数据都存储在叶子节点上

    • 非叶子节点,不是树结构最下面的节点,用于索引数据,存储的的是:key+指针

  • 为了提高范围查询效率,叶子节点形成了一个双向链表,便于数据的排序及区间范围查询

4.2 使用索引和不使用索引的性能差异

为了更好地理解使用索引带来的性能提升,我们来看一个具体的例子。

假设我们有一个包含 100 万条数据的 users 表,其中 name 列没有创建索引。

场景一:不使用索引

SELECT * FROM users WHERE name = '张三';

当执行这条 SQL 语句时,MySQL 数据库需要遍历整个 users 表,逐行比较 name 列的值是否等于 '张三',直到找到匹配的行。这种方式被称为全表扫描,效率非常低下,尤其是在数据量非常大的情况下。

场景二:使用索引

CREATE INDEX idx_name ON users (name);

SELECT * FROM users WHERE name = '张三';

当我们在 name 列上创建了索引之后,再次执行相同的查询语句,MySQL 数据库会直接使用索引进行查找。由于 B+ 树的特性,查找速度非常快,只需要很少的 I/O 操作就可以定位到目标数据。

总结:

使用索引可以避免全表扫描,大大提高查询效率,尤其是在数据量非常大的情况下。

5. 索引失效:问题与解决

虽然索引可以提高查询效率,但在某些情况下,索引可能会失效,导致 MySQL 数据库无法使用索引进行查询,从而进行全表扫描。

常见的索引失效的情况包括:

  • 未使用索引列进行查询: 比如在 WHERE 子句中使用了非索引列进行过滤。

  • 对索引列进行了函数操作: 比如在 WHERE 子句中对索引列使用了函数操作,如 SUBSTR、DATE 等。

  • 使用了 LIKE 模糊查询,且通配符 % 位于开头: 比如 WHERE name LIKE '%三'。

  • 使用了 OR 连接条件,且其中一个条件没有使用索引: 比如 WHERE name = '张三' OR age = 18,如果 age 列没有创建索引,那么整个查询将无法使用索引。

  • 数据分布不均: 如果索引列的数据分布非常不均匀,比如大部分数据的索引列值都相同,那么索引的效率也会降低。

6. 总结

索引是 MySQL 数据库中非常重要的一个概念,合理地使用索引可以大大提高数据库的查询效率。在设计和使用索引时,需要根据实际情况选择合适的索引类型,并尽量避免索引失效的情况。

以上就是关于数据库中索引的相关知识,希望对各位看官有所帮助,下期见,谢谢~


http://www.kler.cn/news/328457.html

相关文章:

  • Nest.js实现一个简单的聊天室
  • The First项目报告:探索Yield Guild Games运行机制与发展潜力
  • Python或R时偏移算法实现
  • 云计算在现代企业中的应用与优势
  • 《软件工程概论》作业一:新冠疫情下软件产品设计(小区电梯实体按钮的软件替代方案)
  • Java中使用Jackson教程
  • C语言、Eazy_x——井字棋
  • 巧用时间换空间:解读 ArcGraph 如何灵活应对有限内存下的图分析
  • TDEngine在煤矿综采管控平台中的应用
  • mysql之函数
  • 循环程序结构课堂练习题解
  • 嵌入式 ADC基础知识
  • Unity DOTS System与SystemGroup概述
  • 网络原理-传输层UDP
  • React【vite使用模块化css】
  • 在 Git 中处理分开提交的文件改动,以便更好地管理版本控制
  • 【30天玩转python】数据分析与可视化
  • P3952 [NOIP2017 提高组] 时间复杂度
  • leetcode:380. O(1) 时间插入、删除和获取随机元素
  • 课设实验-数据结构-线性表-手机销售
  • Android 通过自定义注解实现Activity间跳转时登录路由的自动拦截
  • 【React】入门Day01 —— 从基础概念到实战应用
  • HIVE优化系列之数据倾斜
  • 数据库课程设计案例:在线教育管理系统
  • 51单片机学习第六课---B站UP主江协科技
  • 【STM32单片机_(HAL库)】4-4【定时器TIM】脉冲计数配置步骤及实验
  • 从0开始深度学习(6)——Pytorch动态图机制(前向传播、反向传播)
  • 基础算法--双指针【概念+图解+题解+解释】
  • Arduino UNO R3自学笔记12 之 Arduino在调试过程中串口的使用
  • 【Router】T750路由功能之VLAN划分功能介绍及实现