Oracle里面的COUNT(1)与COUNT(*)函数的执行效率比较。

本文探讨了Oracle数据库中COUNT(1)与COUNT(*)的执行效率,通常认为COUNT(*)会读取所有字段,而COUNT(1)仅统计1的个数,效率更高。但实验结果显示,两者在效率上几乎没有差别,且在有符合条件的索引情况下,都能利用索引。总结得出,COUNT(1)与COUNT(*)在实际应用中效果相当,但在大量数据查询时,推荐使用更简洁的COUNT(*)。
摘要由CSDN通过智能技术生成

目录


前言

 

Oracle中的统计COUNT(*)和COUNT(1)的效率比较,一直以来都是觉得COUNT(1)会比COUNT(*)快一些。至于为什么,我个人以前总觉得*这个符号会将Oracle中所有的字段记录会返回回来,而COUNT(1)只是统计了1的个数,相对比下就自认为COUNT(1)要快一些。然而有一次去参加客户方的一项数据开发时,他们一篇文档中写着COUNT(*)反而要比COUNT(1)快!这严重地打破了之前的认知。基于这个疑问,就尝试写了一下这篇文章,来探讨一下COUNT(1)和COUNT(*)的效率哪个快?

以下是本篇文章正文内容,下面案例可供参考

一、Oracle的存储机制

众所周知,Oracle是关系型数据库。跟Hbase等非关系型数据库不同的一点在于它的存储形式是采用行式存储的。行式存储也就是将表中的数据一行行的写入数据块。而数据块是Oracle的最小单位。每次我们在查询数据的时候,Oracle时常会从磁盘中读取一些数据块到内存中。也就是说你在查询某些字段时,Oracle是把表中一整行的数据读取到内存当中,然后再从头到尾扫描你需要的字段。并非只读取你查询的那几个字段。

二、COUNT(*)与COUNT(字段)的比较

1.COUNT 表中各个字段的比较

如上面所说,Oracle是一行行读取数据,并且在访问字段的时候是根据表中字段的顺序从左往右访问。所以字段在表中的顺序越靠左访问速度越快。为了验证这个设想,进行了如下实验:

/* 
 * 步骤1
 * 目的:创建一张21个字段的的表
 * 大小:1W条记录
*/
CREATE TABLE TMP_TEST_COUNT AS            --创建表
SELECT LEVEL AS ID                        --序号
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT1  --字母,用ASCII计算而来
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT2
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT3
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT4
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT5
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT6
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT7
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT8
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT9
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT10
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT11
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT12
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT13
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT14
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT15
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT16
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT17
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT18
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT19
      ,CHR(65 + MOD(LEVEL, 26)) AS TEXT20
  FROM DUAL
CONNECT BY LEVEL <= 10000;

/*
 *步骤2
 *目的:手动获取表的信息,为了后续SQL执行能有一个正确的执行计划
 */
CALL DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>RPT, TABNAME=>'TMP_TEST_COUNT');


/*
 *步骤3
 *目的:统计各个字段统计的时长
 */
DECLARE
  L_DUMMY PLS_INTEGER;
  L_START PLS_INTEGER;
  L_STOP  PLS_INTEGER;
  L_SQL   VARCHAR2(100);
BEGIN
  FOR I IN 1 .. 20 LOOP
    L_SQL   := 'SELECT COUNT(TEXT' || I || ') FROM TMP_TEST_COUNT';
    
    --因为Oracle有缓存机制,第一次执行的数据会被缓存在内存中,当下次被访问时就不会去磁盘中加载。为了精准测试先加载数据
    EXECUTE IMMEDIATE L_SQL;
    
    L_START :=
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值