全表扫描和全索引扫描

时间:2023-02-17 15:09:18

      有人向我提问: oracle 的select count(*) from table 不走索引,mysql(版本>=5.7) select count(*) from table是自动走索引的,是这样吗?因为提问题的人查过MySQL的count(*)是做过优化的。

要回答这个问题,还是用实验来说明。在Oracle 19C中,我们建立一个表,并且写入100万数据。如图1

全表扫描和全索引扫描

                                                                                       图1

使用Oracle的执行跟踪 set autotrace on; 从实际执行的情况看数据库具体的执行消耗,这样的执行计划更加准备。如图2

全表扫描和全索引扫描

                                                                                   图2

我们看到了 INDEX FAST FULL SCAN。

如果我们查一个不带索引的列,那么比如发生的是全表扫描。如图3

全表扫描和全索引扫描

                                                                                     图3

那么我们来看MySQL的。只用5条就可以说明问题了。xxg表有一个主键。(必须有主键,没有主键就不是这个效果了)。注意看下图有extra中有一个using index。这个在MySQL中叫做索引覆盖。如图4

全表扫描和全索引扫描

                                                                                                                            图4

索引覆盖的意思是仅仅用到了索引,其他没用到。type这里显示的是 index    比如一个表有50列,该表有50G,如果每列长度大致相当,那么其中一列大约有1/50的大小,即1G左右。索引覆盖就是查1G的索引就行,而不是扫描50G。这个就和Oracle中的INDEX FAST FULL SCAN有点相似了。

如果说MySQL对count(*)做了优化,那么也可以说Oracle对count(*)也做了优化。其实我设想,可能就是这样设计的。Oracle和MySQL在这个场景上是一致的。所以不存在一个全表,一个使用索引的区别。(我个人其实觉得全索引扫描、全索引覆盖扫描是用到了索引,但是和我们通常说的用到索引返回少量数据还是有一点区别的)

当然如果没有用到索引,type这里显示的就是ALL了。请看下图5。那么和Oracle的 TABLE ACCESS FULL也是一样的。

全表扫描和全索引扫描

                                                                                   图5