如何让mysql索引更快一点

本文解析了InnoDB中覆盖索引的工作原理,展示了如何利用覆盖索引避免回表操作,从而提高查询效率。通过实例说明了单列索引与复合索引在查询性能上的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

在 InnoDB 中,从二级索引回到主键索引查询数据,这个过程称作回表过程,而且这个回表过程是可以被优化的,这个优化就是利用覆盖索引

 

先说结论,如果一个索引的字段包含了所有要查询的字段,这个索引就称作覆盖索引,覆盖索引可以减少回表过程,能有效提高查询效率

 

前面我们有说过,在 InnoDB 中数据都是保存在 B+ 树上,主键索引保存了整行记录,二级索引保存了主键的值。

 

一次查询操作,要么是遍历主键索引,要么是遍历二级索引,要么就是先遍历二级索引得到主键 id 的值,然后再到主键索引上通过主键 id 查找满足要求的记录。

 

如果只遍历一次 B+ 树就能获取到我们要的数据,即没有回表过程,这个效率显然是不错的,这就是覆盖索引的优势。下面看个具体的例子。

 

mysql> create table user(
id int(11) primary key, 
name varchar(20) not null, 
age int(11),
sex int(11),
index (age)) engine=InnoDB;

 

依然是新建一个表,创建索引,插入一些测试数据,注意这里只是为了解释说明覆盖索引,并不表示 mysql 的真实执行方式,因为会涉及到 mysql 的优化器机制,这里暂且不说了,以后再写。

 

1    bob 16  1
2    kom 19  0
3    gum 18  1
4    tt  20  1
5    yy  25  1

 

创建一个 user 表,给 age 字段添加一个二级索引,并插入上面五条数据,然后看下面这条查询语句。

 

select name from user where age between 18 and 21

 

我们来分析下这条 sql 的执行过程:

 

1、age 字段上有索引,mysql 会先到 age 字段的 B+ 树上找到满足条件的第一个叶子节点(age=19),这个叶子节点上保存了对应主键 id 的值 2,然后再到主键索引上找到 id 为 2 的这条记录,同时把 name 字段拿出来。

 

2、重复第一步的操作,继续从 age 索引上的叶子节点往后遍历找出满足条件的第二个叶子节点,同样回到主键上拿出 name 字段的值,直到遍历到不满足条件的叶子节点(age=25)。

 

也就是说,这条 sql 语句虽然用到了索引,但是 age 索引上并没有要查询的 name 字段,所以只能回表到主键索引上查出 name 字段,所以这个过程其实是遍历了个两个 B+ 树。

 

那么我们删除 age 这个单列索引,创建一个覆盖索引 (age,name), 把要查询的 name 字段也添加到索引中来。

 

#删除原索引
drop INDEX age on USER
#新建覆盖索引
ALTER TABLE USER add index age_name(age,name)

 

由于现在这个覆盖索引上的字段包含了要查询的 age 和 name 字段,免去了到主键索引上查询数据的过程,其实也就是只遍历了一个 B+ 树,可以大大提升查询效率。

 

添加索引虽然能提升查询效率,但索引也是需要占用额外空间的,而且索引还需要维护成本,所以通常加不加索引需要根据实际需求来权衡。

 

总之,在设计索引或者优化 sql 语句的时候,要尽量避免回表操作,所以使用覆盖索引是一种常用的 sql 优化手段。

 

所以我们平时写 sql 语句的时候,select 后面只写查询需要用到的字段,去掉不需要的字段,避免回表操作。

 

有问题欢迎大家留言交流,原创不易,如果文章对你有帮助,欢迎点赞,感谢支持。

### MySQL 唯一索引的工作原理 在 MySQL 中,唯一索引(Unique Index)是一种特殊的索引类型,它确保了索引列中的所有值都必须是唯一的。这意味着在一个表中定义了一个唯一索引之后,任何试图向该列插入重复值的操作都会被拒绝并抛出错误。 唯一索引通常基于 B+Tree 数据结构实现[^1]。B+Tree 是一种平衡树结构,在这种结构下,数据按照键值有序存储,并且每个节点可以保存多个键值和指针。通过这种方式,查询操作可以通过二分查找快速定位目标记录的位置,从而显著提升性能。 当创建唯一索引时,MySQL 实际上会在后台维护一棵 B+Tree 来管理这些索引条目。每当有新的数据插入或者更新时,数据库引擎会先检查这棵 B+Tree 是否已经存在相同的键值。如果发现冲突,则立即返回失败;如果没有冲突,则将新记录加入到对应的叶子节点位置。 ### 性能优势分析 #### 1. **减少冗余数据** 由于唯一索引强制要求字段内的值不可重复,因此它可以有效防止因意外输入而导致的数据冗余现象发生。这样不仅节省了磁盘空间占用量,同时也降低了后续处理过程中可能出现的各种复杂度问题[^2]。 #### 2. **加速特定条件下的查询速度** 对于那些经常用于过滤条件 (WHERE 子句) 的列来说,为其建立唯一索引往往能够带来明显的效率增益效果。这是因为相比起普通的全表扫描方式而言,利用已有的索引来完成相同任务所需消耗的时间成本要低得多——尤其是在面对大规模数据集的时候更是如此[^3]。 另外值得注意的是,某些情况下我们还可以通过对较长字符串类型的字段预先计算哈希值后再单独建一个小型整数型辅助列来进行联合索引设置,以此进一步优化整体表现水平[^4]。 ```sql -- 创建带有 UNIQUE 约束的索引示例 CREATE TABLE example_table ( id INT AUTO_INCREMENT PRIMARY KEY, email VARCHAR(255), CONSTRAINT uc_email UNIQUE (email) ); -- 插入测试数据 INSERT INTO example_table(email) VALUES('test@example.com'); -- 尝试再次插入同样的邮箱地址将会报错 INSERT INTO example_table(email) VALUES('test@example.com'); ``` 以上代码片段展示了如何在 `example_table` 表上的 `email` 列应用唯一约束。尝试第二次插入同一电子邮件地址会导致违反唯一性限制而引发异常情况。 ### 结论 综上所述,MySQL 的唯一索引因其内在机制设计特点而在实际应用场景当中展现出了诸多方面的优越之处:既可以从逻辑层面保障业务规则得以严格执行,又能在物理层面上极大程度地改善系统运行效能指标。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值