mysql回表怎么避免,mysql 回表 什么意思

【Mysql】查询优化——减少回表操作

  聚集索引:数据行的物理顺序与列值(一般是主键的那一列)的逻辑顺序相同,一个表中只能拥有一个聚集索引。 叶子结点存储索引和行记录,聚簇索引查询会很快,因为可以直接定位到行记录。

创新互联成立于2013年,是专业互联网技术服务公司,拥有项目网站制作、做网站网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元西乡做网站,已为上家服务,为西乡各地企业和个人服务,联系电话:18982081108

  非聚集索引:该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引。 叶子节点存储聚簇索引值(主键id),需要扫码两遍索引树,先通过普通索引定位到主键值id,再通过聚集索引定位到行记录。

  回表查询可以理解为普通索引的查询,先定位主键值,再定位行记录,它的性能较扫一遍索引树更低。

  索引覆盖,即将查询sql中的字段添加到联合索引里面,只要保证查询语句里面的字段都在索引文件中,就无需进行回表查询;

  实际开发中,不可能把所有字段建立到联合索引,可根据实际业务场景,把经常需要查询的字段建立到联合索引中。

   在Mysql5.6的版本上推出,用于优化查询。 在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。

   优化超多分页场景。 查询条件放到子查询中,子查询只查主键id,然后使用子查询中确定的主键关联查询其他的属性字段。

2020-07-12:什么是索引回表,如何避免?

通过索引查数据其实是分两步:

1、通过索引字段查到数据的主键ID

2、通过主键ID查询全部数据

其中第二步就是索引回表,要避免索引回表,就要保证查询的数据只包含主键和索引字段本身,这样第二步就可以省了

数据库回表

一张用于用户登录的user表:id、userName、Password三个字段

再根据查出来的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语句改一下

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

那我们应该如何避免回表,因为如果用到了回表,就需要二次查询的过程,效率肯定更慢,很简单,回表是因为要查询的字段在非聚集索引里没有,所以在满足需求的情况下,我们尽量使非聚集索引里有要查询的索引字段。

在查询时,可以尽量用聚集索引来查(也就是用主键来查询),或者根据业务需求,建好的索引,满足索引查询字段。但是实际业务中,很难建立一个索引就能满足所有查询要求,所以,正常情况,回表也没事,只要能用到索引也能大大加快查询速度。

阿里三面:MySQL回表的性能伤害有多大?

无论单列索引 or 联合索引,一个索引就对应一个独立的B+索引树,索引树节点仅包含:

即使根据索引树按条件找到所需数据,也仅是索引里的几个字段的值和主键值,万一你搞个select *,那就还得其他字段,就需回表,根据主键到聚簇索引里找,聚簇索引的叶节点是数据页,找到数据页才能把一行数据所有字段值读出来。

所以类似

得从联合索引的索引树里按序取出所有数据,接着对每条数据都走一个主键的聚簇索引查找,性能不高。

有时MySQL执行引擎可能认为,你要是类似

相当于得把联合索引和聚簇索引,两个索引的所有数据都扫描一遍,那还不如不走联合索引,直接全表扫描得了,这样就只需扫描一个主键索引。

但若形如:

那执行引擎就知道你先扫描联合索引的索引树,拿到10条数据,接着对10条数据在聚簇索引里查找10次即可,那就还是会走联合索引。

覆盖索引不是一种索引,只是一种基于索引查询的方式,即针对类似

仅需联合索引里的几个字段的值,那就只需扫描联合索引的索引树,无需回表找其它字段,这种查询方式就是覆盖索引。

所以当你使用联合索引时,注意是否可能会导致大量回表到聚簇索引,若回表聚簇索引的次数太多,可能就直接给你做成全表扫描而不走联合索引了。

尽可能还是在SQL里指定你仅需要的字段,而不要暴力select *,最好直接走覆盖索引。

即使无可避免地要回表,你也尽可能用limit、 where限定一下回表的次数,就从联合索引里筛选少数数据,再回表,这样性能好一点。


当前标题:mysql回表怎么避免,mysql 回表 什么意思
转载来源:http://azwzsj.com/article/dsggdgp.html