oracle中count(1)和count(*)之间的区别

时间:2018-07-21 23:07:19

标签: sql oracle

通过多种资源,书籍和问题,我发现count(1)count(*)之间没有区别。我发现count(1)count(*)快。 但是我真的不知道怎么办? 据我所知,count(*)计算rowid,而count(1)计算1作为行数。由于rowid是18位字符,是否需要更多时间?据我所知,大小是2还是38,速度并不重要。

任何人都可以消除我的疑问。

4 个答案:

答案 0 :(得分:12)

我相信count(1)在旧版本的Oracle中曾经更快。但是到目前为止,我很确定优化器足够聪明,可以知道count(*)count(1)意味着您需要行数并创建适当的执行计划。

您在这里:

create table t as select * from all_objects;

Table T created.

create index tindx on t( object_name );

Index TINDX created.

select count(*) from t;

  COUNT(*)
----------
     21534

select * from table(dbms_xplan.display_cursor( NULL, NULL, 'allstats last' ));

Plan hash value: 2940353011

--------------------------------------------------------------------------------------------------
| Id  | Operation             | Name  | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |       |      1 |        |      1 |00:00:00.01 |     100 |     93 |
|   1 |  SORT AGGREGATE       |       |      1 |      1 |      1 |00:00:00.01 |     100 |     93 |
|   2 |   INDEX FAST FULL SCAN| TINDX |      1 |  18459 |  21534 |00:00:00.01 |     100 |     93 |
--------------------------------------------------------------------------------------------------

select count(1) from t;

  COUNT(1)
----------
     21534

Plan hash value: 2940353011

-----------------------------------------------------------------------------------------
| Id  | Operation             | Name  | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |       |      1 |        |      1 |00:00:00.01 |     100 |
|   1 |  SORT AGGREGATE       |       |      1 |      1 |      1 |00:00:00.01 |     100 |
|   2 |   INDEX FAST FULL SCAN| TINDX |      1 |  18459 |  21534 |00:00:00.01 |     100 |
-----------------------------------------------------------------------------------------

因此,不仅知道它可以使用索引来优化此查询还足够聪明,而且针对不同版本使用了完全相同的执行计划(计划具有相同的价值)。

答案 1 :(得分:3)

count(1)和count(*)现在在oracle中都是相同的,如果可用,都使用index,并且count也为Null。 count(1)只是将行数据替换为1,然后对数字1进行计数,count(*)对行的计数可能基于rowid。

答案 2 :(得分:2)

我认为这个谣言的起源是假设数据库必须在内部将*扩展到完整的列列表中,因此用诸如count('Dracula')之类的文字巧妙地避免了这种开销。但事实并非如此,而且从未如此。我是1990年在Oracle 6上第一次听说的(另一个变化是您应该使用PK列),然后那不是真的。

标准证明之一(除了检查它是否对性能有实际影响外,不会对性能产生任何影响)是检查执行计划的“谓词”部分,其中在谓词中使用count(1)

SQL> select dummy from dual group by dummy having count(1) = 1

SQL> @xplan
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
Compatibility is set to 12.2.0.0.0

Plan hash value: 795860295

------------------------------------------------------------------------------
| Id  | Operation             | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |      |     1 |     2 |     3  (34)| 00:00:01 |
|*  1 |  FILTER               |      |       |       |            |          |
|   2 |   SORT GROUP BY NOSORT|      |     1 |     2 |     3  (34)| 00:00:01 |
|   3 |    TABLE ACCESS FULL  | DUAL |     1 |     2 |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(COUNT(*)=1)

请注意,优化程序已替换了COUNT(*)

count(1)所要做的就是为您提供更多的按键输入方式,并使您看起来像一个相信谣言的人。

答案 3 :(得分:2)

我已经测试了两个简单的查询,它们在Oracle和其他一些RDBMS中的1M行上计算了COUNT(*)COUNT(1),但在Oracle中没有发现任何区别。 See this post for details

但是,在PostgreSQL 11.3中,看来COUNT(1)慢了大约10%,因为PostgreSQL不会将表达式转换成COUNT(*),因此在运行{{ 1}}。