自学内容网 自学内容网

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

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


原文地址:https://blog.csdn.net/weixin_64178283/article/details/142599781

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!