openGauss

开源数据库

openGauss社区官网

开源社区

什么是数据库回表操作

张翠娉2022-09-23数据库入门

什么是数据库回表操作

什么是回表? 可以举一个简单的例子,我有一张用于用户登录的 user 表:

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

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

sql
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 语句改一下

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

sql
SELECT password FROM user WHERE username = 'admin'

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