签到成功

知道了

CNDBA社区CNDBA社区

听说count(8) 比count(*) 快好多,是真的吗?

2017-03-22 15:55 2867 1 转载 Oracle 性能优化
作者: Expect-乐

本文已获原作者授权转载。文章出自微信公众帐号:老虎刘谈SQL优化

作者介绍:老虎刘,原oracle 研发部门 Real-World Performance TEAM 成员,现在售后部门SSC专职做数据库性能优化,主要为银行、通信、证券、制造等大型企业提供服务。


央视有个黄西博士主持的节目,叫做《是真的吗?》,会以实验的方式验证一些奇奇怪怪的问题。


那我们今天就来验证一个神奇的事情:count(8) 会比count(*) 快很多倍,是真的吗?


首先我们先炮制一个1千万的大表:T10M,这是一个占用空间1.2G的普通表,没有任何索引。建表过程略。


速度对比验证开始:

SQL>set timing on 

SQL> select count(*) from t10m; 

COUNT(*) http://www.cndba.cn/Expect-le/article/1823

---------- 

10000000 

Elapsed: 00:00:05.33 

http://www.cndba.cn/Expect-le/article/1823

SQL> select count(8) from t10m;

 COUNT(8) 

---------- 

10000000 

Elapsed: 00:00:00.75


哇,非常神奇,5.33秒 VS 0.75秒,整整7倍的性能差距,难道就是因为一个少敲了一个shift键吗(为了娱乐效果,故意使用了count(8),等同于常见的count(1))。

通过实验结果,这个结论看起来确实是真实的。

http://www.cndba.cn/Expect-le/article/1823
http://www.cndba.cn/Expect-le/article/1823










如果是初学者,看了上面的结论,没有接着往下看,可能真的会回去把代码里面的count(*) 都改成了count(8),这样一个天大的秘密怎么今天才知道呢?!


别急,实验还没完。如果我们再执行一次count(*),看看发生了什么:

SQL> select count(*) from t10m; 

COUNT(*) 

---------- 

10000000 

Elapsed: 00:00:00.63

这次count(*) 反而又比count(8) 速度快了,神马情况?


http://www.cndba.cn/Expect-le/article/1823

内存的读取速度要比磁盘快是路人皆知的事实,第一次的PK实际上就是磁盘读与内存读的区别(这里不多解释),根据执行计划,count(*) 与 count(8) (通常都习惯写成count(1))在性能上根本就没有任何区别。


之前得到的结论就是在不清楚数据库原理的情况下,得到的片面结论。如果把这个结论当成一般性结论加以推广,岂不是贻笑大方。


有人可能会比较奇怪,老虎刘为什么故弄玄虚搞出这么一个小儿科的案例来欺骗大家的感情?http://www.cndba.cn/Expect-le/article/1823


因为老虎刘在一本书上看到一个优化案例,说是

sql1:select rowid from t_xxx where rownum<=1;

的性能要比

sql2:select count(1) from t_xxx where rownum<=1;http://www.cndba.cn/Expect-le/article/1823

好。

瑕不掩瑜,书还是一本好书,写了作者的一些实际运维技巧和案例,我也学到了一些技巧,具体书名就不在这里说了


作者是通过set autotrace on ,分别执行sql2和sql1(注意执行顺序),然后比较两次sql执行显示的 consistent gets数来判断两个SQL的性能情况。 实验结果显示确实是sql2消耗的 consistent gets要比sql高很多(我的实验结果是770 : 5)。由此得出上面的结论。http://www.cndba.cn/Expect-le/article/1823


我第一次看到这个案例的时候,就非常怀疑。因为是专家写的案例,万一是真的我还学了一招。于是我通过实验验证了一下,结果如我所料,两个SQL基本上没有什么区别


sql2第一次执行时,因为recursive calls次数多,消耗了绝大部分的consistent gets。再执行sql1时,不需要那么多的recursive calls了,consistent gets确实少了很多。

如果再次执行SQL1和SQL2,都是只有3个consistent gets,没有任何差别。而sql2执行计划中多出来的一步 SORT AGGREGATE,在CPU看来基本上是可以忽略的。http://www.cndba.cn/Expect-le/article/1823


如果实验顺序是先执行sql1,再执行sql2,反而就会得出sql2的性能比sql1好的结论来。


总结:

我要表达是意思是,我们要通过理论来指导测试,而不是把片面的测试结果当成一般性结论,这样会误导自己,更会误导广大的读者。尤其是对一些有影响力的专家,在做出一些结论的时候,最好看看是不是有理论根据。


顺便提一句,select ... from a where a.id in (select b.id from b);这种SQL,如果要改成表关联,不是

select distinct .... from a,b where a.id=b.id; 两者是不等价的。

等价改写是: select .... from a,(select distinct b.id from b) bb where a.id=bb.id;  注意distinct的位置。http://www.cndba.cn/Expect-le/article/1823

用户评论
* 以下用户言论只代表其个人观点,不代表CNDBA社区的观点或立场
Expect-乐

Expect-乐

关注

Without the continuous bitter cold, there can be no fragrant plum blossom

  • 336
    原创
  • 6
    翻译
  • 100
    转载
  • 41
    评论
  • 访问:1378110次
  • 积分:1957
  • 等级:核心会员
  • 排名:第3名
精华文章
    最新问题
    查看更多+
    热门文章
      热门用户
      推荐用户
        Copyright © 2016 All Rights Reserved. Powered by CNDBA · 皖ICP备2022006297号-1·

        QQ交流群

        注册联系QQ