通过多种资源,书籍和问题,我发现count(1)
和count(*)
之间没有区别。我发现count(1)
比count(*)
快。
但是我真的不知道怎么办?
据我所知,count(*)
计算rowid
,而count(1)
计算1作为行数。由于rowid
是18位字符,是否需要更多时间?据我所知,大小是2还是38,速度并不重要。
任何人都可以消除我的疑问。
答案 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}}。