暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

总在面试时被问COUNT(*)、COUNT(1)哪个快?

InDataBase 2021-04-26
1372

总有人说在面试时会被问COUNT(*)、COUNT(1)哪个快?

这次就来说说我的理解。


COUNT有三种格式:

⊙ COUNT(*)  

COUNT(*)可以返回表中行的数量,包括重复的行和任意列中部分包含有空值的行。 


⊙ COUNT(expr) 

返回由expr标识的列中非空值的数量 


⊙ COUNT(DISTINCT expr) 

返回由expr标识的列中非空值的不重复值的数量 


实验一下,看结果更直观:

先创建表,加入三条数据


分别执行查询,看看结果理解不


知道了COUNT的格式,下面来看看这个实验:

创建一张表,并加入测试数据。

并在object_id 创建一个索引


查看表结构,确认object_id 可为空


打开查看执行计划,执行Select count(*) from t;

走了全表扫描,如果一个表很大,全表扫描一下 很消耗资源。


执行Select count(1) from t;

和count(*) 一样 也是全表扫描。


再执行一下Select count(OBJECT_ID) from t;

走了索引扫描


那为什么会走索引不走全表扫描呢 ?

我们知道 count(列) 是不会统计列的NULL值的

而且索引里面也不会记录空值

所以我们可以走索引去计算


回看两个执行计划的cost,看索引扫描成本才26,比155少了很多。


继续试验。

把object_id列 修改为不可为空的


再执行Select count(*) from t;

查看count(*)的执行计划,这次走了索引

因为这个字段是NOT NULL,所以它的索引的条数 和记录的总条数是一样


执行Select count(1) from t;

结果也是一样



听到有人说count(1) 比count(*)性能好

通过咱们刚才的实验来看Count(1)和count(*)其实几乎没有什么区别。


小结一下:

COUNT(列名),能用上索引。

COUNT(*)、COUNT(1),如果索引列定义为非空,则能用上,否则用不上。

COUNT(*)与COUNT(1)没有区别。


别急着记结论,往下看


创建了一个t3表,只有object_id一列

我们创建了索引,并把这列修改为NOT NULL


我们执行一下 select count(*) from t3;

竟然不走索引


迷糊不,刚背完的结论怎么不成立了呢?


其实道理很简单:

索引要记录一列的值和物理地址

比表还多了个物理地址这一个东东

使得索引的总体积变成行数*(列的长度+物理地址的长度)

那这样算的话 索引是不是比表还要大了

表存放了10个数据块 你索引都存放了20个数据块 

那我肯定是扫描这10个数据块更好

Oracle也是这么想的,所以优化器权衡下选择了全表检索。


所以在索引比全表快的前提下,之前的小结的部分才成立。


文章转载自InDataBase,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论