网络编程
位置:首页>> 网络编程>> 数据库>> 一文弄懂什么是MySQL的回表

一文弄懂什么是MySQL的回表

作者:逆流°只是风景-bjhxcc  发布时间:2024-01-22 16:56:56 

标签:MySQL,回表

一、背景

先要从 InnoDB 的索引实现说起,InnoDB 有两大类索引:

  • 聚集索引 (clustered index)

  • 普通索引 (secondary index)

InnoDB 聚集索引和普通索引有什么差异?

InnoDB 普通索引 的叶子节点存储主键值。

注意:只有 InnoDB 普通索引才存储主键值,MyISAM 的二级索引都是直接指向数据块的。

InnoDB 聚集索引 的叶子节点存储行记录,因此,InnoDB 必须要有,且只有一个聚集索引:

如果表定义了主键,则主键就是聚集索引;

如果表没有定义主键,则第一个 not null 的 unique 列是聚集索引;

否则,InnoDB 会创建一个隐藏的 row-id 作为聚集索引;

注意:所以主键查询非常快,直接定位行记录。

二、什么是回表查询?

通俗的讲就是,如果索引的列在 select 所需获得的列中(因为在 mysql 中索引是根据索引列的值进行排序的,所以索引节点中存在该列中的部分值)或者根据一次索引查询就能获得记录就不需要回表,如果 select 所需获得列中有大量的非索引列,索引就需要到表中找到相应的列的信息,这就叫回表。

InnoDB聚集索引的叶子节点存储行记录,因此, InnoDB必须要有,且只有一个聚集索引:

(1)如果表定义了主键,则PK就是聚集索引;
(2)如果表没有定义主键,则第一个非空唯一索引(not NULL unique)列是聚集索引;
(3)否则,InnoDB会创建一个隐藏的row-id作为聚集索引;

三、可以举一个简单的例子

我有一张用于用户登录的user表:

字段名类型说明
idbigint(20)主键ID
usernamevarchar(20)用户名
passwordvarchar(20)密码

假如现在有一个用户名为admin,密码为123的用户要登录,那我会先找出username为admin的那条用户数据

SELECT * FROM user WHERE username = 'admin'

再根据查出来的user信息去对比密码是否正确

这时你发现username字段是唯一的又经常作为where条件所以可以给username字段建一个索引,于是就给username建了一个普通的B+Tree索引。

这时候就出问题的,因为MySQL的InnoDB使用聚簇索引,具体的数据只和主键索引放在一起,其他的索引只存储了数据的地址(主键id)。

比如上面的例子中,我根据username索引找到的只是一个username为admin这条数据的id而不是这条数据信息,所以要找到整条数据信息要根据得到的id再去找。

看完上面的流程,你应该已经发现问题了,我要通过username找到id,再根据id找整条数据,这里有两个查找过程,这是影响效率的。就像上面的两个查找过程就是回表了。

四、解决办法

使用覆盖索引可以解决上面所说的回表的问题。
还是拿上面上面登录的例子来说,其实登录只需要判断用户名和密码,如果user表中有其他用户信息也是不需要的那我们能不能只查询一次就找到这个用户名对应的密码呢。

这个是可以的,上面所说的分两步查找,第一步根据username查找是肯定不能少的,那我们只要把password和索引username放到一起就可以了。我们可以建立一个(username、password)的组合索引,这里username一定要放在前面,然后我们把sql语句改一下

SELECT username, password FROM user WHERE username = 'admin'

SELECT password FROM user WHERE username = 'admin'

这样建立组合索引后根据username查找password,只要一步查找就可以查找到,因为password已经是username索引的一部分了,直接可以查出来,不再需要通过id找对应的整条数据。覆盖索引就是覆盖了多个列(字段)的索引。

五、更多如下图:

一文弄懂什么是MySQL的回表

(1)先通过普通索引定位到主键值id=5;
(2)在通过聚集索引定位到行记录;

这就是所谓的回表查询,先定位主键值,再定位行记录,它的性能较扫一遍索引树更低。

六、总结

使用聚集索引(主键或第一个唯一索引)就不会回表,普通索引就会回表。

来源:https://blog.csdn.net/u011397981/article/details/129724738

0
投稿

猜你喜欢

  • split函数主要应用场景是Python对字符串的处理中(数据分析,数据处理),以及计算机二级考试的常考基础知识点。一、split函数的官方
  • 初识word文档-节-的概念编辑一篇word文档,往往首先从页面设置开始,从下图可以看出,页面设置常操作的有页边距、纸张方向、纸张大小4个,
  • mat矩阵和npy矩阵互相转换numpy.narray矩阵保存为mat文件import numpy as npimport scipy.io
  • 前言最近需要源码部署一个项目,因此探索一下保护源码的方式,由简单到复杂主要总结为以下三大类:代码混淆:主要是改变一些函数名、变量名代码打包:
  • 导语之前有很多小伙伴说想学习一下多线程图片下载器,虽然好像已经过去很久了,不过还是上来安排一波吧。至于题目为什么说是构建一个小型数据集,因为
  • 很多网站都有此功能,当浏览到底部时都会有一个打印按钮,点击打印按钮就可以完成打印功能,功能非常不错,人性化,代码非常的简单。<a hr
  • 1.什么是并发编程并发编程是实现多任务协同处理,改善系统性能的方式。Python中实现并发编程主要依靠进程(Process):进程是计算机中
  • 前言超时,指一个协程A开启另一个协程B,A会阻塞等待B一段指定的时间,例如:5秒,A通知B结束(也有可能不通知,让B继续运行)。也就是说,A
  • 目录简述:实战案例:简述:关于敏感词过滤可以看成是一种文本反垃圾算法,例如 题目:敏感词文本文件 filtered_words.t
  • 1.1.1 摘要 如果说要对数据库进行优化,我们主要可以通过以下五种方法,对数据库系统进行优化。 1. 计算机硬件调优 2. 应用程序调优
  • 01、正则表达式学习正则表达式操作字符串,re模块是用C语言写的没匹配速度非常快,其中compile函数根据一个模式字符串和可选的标志参数生
  •   可以,具体方法如下::<% set fs=createobject("scripting.
  • nonzero函数返回非零元素的目录。返回值为元组, 两个值分别为两个维度, 包含了相应维度上非零元素的目录值。  import
  • 一个朋友需要,所以写了这两个,话不多说,看代码中国电信号段 133、149、153、173、177、180、181、189、199中国联通号
  • 所谓天赋(左脑和右脑)也就是你是否有艺术天赋,天赋也许是存在的,这主要在于人类左右脑的分工。左脑主要负责逻辑理解、语言、判断、分类、分析、推
  • 当我们需要将一个一维数组转换成一个多层结构的时候,最简单但是最慢的就是多个for循环嵌套,但是这样做有一些缺点,那就是效率太低、而且有多少层
  • 本文为大家分享了python实现俄罗斯方块游戏的具体代码,供大家参考,具体内容如下Github:Tetris代码:# -*- coding:
  • 先上图片词云图需要模板pip install jiebapip install wordcloud还需要安装另外两个东西这两个我也不太懂借鉴
  • 本文实例讲述了Python二叉树定义与遍历方法。分享给大家供大家参考,具体如下:二叉树基本概述:二叉树是有限个元素的几个,如果为空则为空二叉
  • 大家既然能看到这个视频,说明大家对跨域已经有了一定的理解,所以这里就不花功夫对跨域进行详细的介绍了1. 首先扩展一点,axios在本地发送的
手机版 网络编程 asp之家 www.aspxhome.com