MySQL回表机制解析与优化策略

一,MySQL中的回表是什么意思?

利用二级索引进行查询除索引列值和主键以外的值时,由于二级索引的叶子节点中存储的只有索引所对应列的值和主键id,这样就导致我们查询不到,所以Innodb就会重新使用查到的主键id回到表中找到对应的行数据,因为主键索引的叶子节点存储的是对应行的全部数据,所以可以找到

举个例子,这里使用select * from user where age = 20;来进行举例说明,user表上有三个字段,分别是id,name,age,这里age上有索引

(1)首先走age的二级索引,找到age = 20 的记录拿到主键值

(2)由于我们使用了select * 导致我们还需要name字段,但是age索引中并没有name,这时我们要用找到的主键id重新回到表中,找到全部对应行数据字段id,name,age

二,回表所带来的性能代价

回表并不是重新查询一遍表那么简单

因为查询二级索引所查询到的主键id并不是连续的,就比如age = 20 的用户有很多,所以查询到的id是无序的,可能的顺序:10,239,3,2134,21390,使用这些id去主键索引中查,会导致定位到不同的数据页,从而产生大量的随机IO

顺序IO:读写的数据在磁盘上是一个挨着一个的,读取一大块相邻磁盘页,磁头也会很快的进行移动,不会出现较大幅度的移动

随机IO:读写的数据分布在磁盘上的随机位置,如果数据一多,那么效率将会有很明显的下降

三,如何避免/减少回表

1.覆盖索引

如果我们想避免回表,那么我们就要让所查询字段出现在二级索引中,就比如我建立索引为idx_name_age(name,age),那么select name from user where age = 20就不会进行回表,索引的叶子节点就存储了id,name,age,直接返回就ok了

2.索引下推

这个功能是在MySQL5.6之后才出现的,索引下推(index condition pushdown)ICP将一些where条件下推到引擎层先进行过滤,再对过滤后的条件进行回表,没有通过的条件直接就不回表了,这样可以大大减少回表的次数

举个例子现在依旧一个索引idx_name_age(name,age),where name ='张%' and age = 20,如果没有ICP那么先查询到姓张的人的id,然后对这些人全部进行回表,回表后拿到的数据再进行age=20过滤,如果开启索引下推,那就会先找到name ='张%'的范围,然后再在索引叶子节点中找到过滤age=20这样就少回表不符合条件的了

3.减少select *的使用

使用这个select *基本上肯定要回表,所以就不要图方便随便使用这个select *

四,如何判断查询有没有回表

看Explain中的Extra值,如果是Using Index那么是覆盖索引,没有回表,如果是Using Index Conditiion,那么就是发生了ICP回表了,如果type值为Index,表示全索引扫描,不一定发生了回表

五,主键查询需要回表吗

不需要回表,主键索引的叶子节点中就包含整列数据,直接就可以查到不需要回表

相关推荐
circuitsosk1 小时前
向量数据库选型与性能压测:Milvus、Pinecone、Chroma在真实业务下的对比
数据库·python·pinecone·milvus·向量数据库·chroma
影寂ldy1 小时前
SQL 索引(Index)完整笔记
数据库·笔记·sql
切糕师学AI1 小时前
从压缩到查询:PostgreSQL中JSON数据的存储与处理实践
数据库·postgresql·json
渣渣盟1 小时前
当 Redis 写入成为性能瓶颈时,如何利用 异步批量 Sink 将吞吐量从 1w QPS 提升到 10w+?
数据库·redis·php
SelectDB1 小时前
Apache Doris 2026 Roadmap:AI 成为主流负载后数据基础设施的演进方向
数据库
SelectDB2 小时前
瓴岳科技洋钱罐 SelectDB Hive 透明加速:湖仓一体化探索分析平台升级实践
数据库
SelectDB2 小时前
飞轮科技 SelectDB Enterprise 4.0.5:企业级实时分析与 AI 数据底座的安全治理实践
数据库
SelectDB2 小时前
金城银行 Apache Doris 实时数据平台:从 T+1 到分钟级的金融级高可靠实践
数据库
SelectDB2 小时前
Apache Doris 4.1:面向 AI & Search 的统一数据存储与检索底座技术能力
数据库