数据库索引 “回表“ 问题

什么是回表?

 

 

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

案例:

测试环境:与上述相同

测试sql:

sql1:select brand from index_basedata where year = 2018 group by day limit 5;

执行时间:21.8s

explain一下:
数据库索引 “回表“ 问题

 

使用了索引“year”, 则索引列为year,但是select brand from..中brand并不是索引列,就需要回表(通过图也可以看出,进行了tablescan,另外其中的IndexLookUp也说明了进行了回表),所以花费时间长

sql2:select brand from index_basedata where year = 2018 group by year limit 5;

执行时间:21.7s

explain一下:

数据库索引 “回表“ 问题

使用了索引“year”, 则索引列为year,但是select brand from..中brand并不是索引列,就需要回表(通过图也可以看出,进行了tablescan,另外其中的IndexLookUp也说明了进行了回表),所以花费时间长,另外,对于sql2中的group by使用的是索引列,所以使用的StreamAgg,不同于sql1

sql3:select year from index_basedata where year = 2018 group by year limit 5;

执行时间:2.5s

explain一下:

数据库索引 “回表“ 问题

可以看到:没有tablescan,也没有使用IndexLookUp而是IndexReader说明直接从索引中读取索引列并使用。

总结:在上述案例中,sql3使用了索引列,没有进行回表,sql1与sql2进行了回表,所以花费时间长。所以说,发生严重的回表的时候,查询速度比不使用索引还慢。

那么,下面的5个sql执行时间能不能理解呢?
select year from xcar_index_basedata_noprice where year = 2018 group by year limit 5;

select month from xcar_index_basedata_noprice where month = 201807 group by month limit 5

select brand_id from xcar_index_basedata_noprice where month = 201807 group by month limit 5;

select brand_id from xcar_index_basedata_noprice where year = 2018 group by year limit 5;

select brand_id from xcar_index_basedata_noprice where year = 2018 group by month limit 5;

对应执行时间:

数据库索引 “回表“ 问题