oracle中count(1)和count(*)之间的差异

Onk*_*ari 14 sql oracle

通过多种来源,书籍和问题,我发现count(1)和之间没有区别count(*).我找到的地方count(1)比...更快count(*).但我真的不知道怎么样?据我所知,count(*)计算rowidcount(1)计算1作为行数.因为rowid18位数的字符需要更多时间吗?据我所知,尺寸是2还是38,速度无关紧要.

你们中的任何人都可以清楚我的怀疑.

eao*_*son 13

我相信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 |
-----------------------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

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

  • 据我所知,从来没有一个版本的Oracle计算某些任意文字比标准表达式更快.我明确地回忆起围绕Oracle 6时间框架这样的声明,而且它们也不是真的. (2认同)
  • 执行计划不会告诉您SORT AGGREGATE操作的细节差异。可能会大不相同。例如,当[`expr`的类型为NUMBER的类型比[BINARY_DOUBLE]的类型时,聚合`SUM(LN(expr))`的速度可能会慢几个数量级(https://blog.jooq.org/2019/09 / 11 / oracles-binary_double可能比number /快得多),但是您不会在执行计划中看到它。 (2认同)

Wil*_*son 5

我认为这个谣言的起源是假设数据库必须在内部扩展*到完整的列列表,因此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)
Run Code Online (Sandbox Code Playgroud)

请注意,优化器已替换COUNT(*).

所有count(1)做的就是给你更多的按键输入,让你看起来像一个人谁相信谣言。

  • 我个人使用 count(2),这使它的速度提高了一倍;-) (5认同)
  • @tbone:我使用 `count(-1)`,它在我开始之前就已经完成计数了。 (3认同)

Luk*_*der 5

我已经在 Oracle 和其他一些 RDBMS 中测试了两个计算1M 行COUNT(*)或的简单查询COUNT(1),但没有发现 Oracle 中存在任何差异。详细信息请参阅这篇文章

然而,在 PostgreSQL 11.3 中,似乎COUNT(1)慢了大约 10%,因为 PostgreSQL 不会将表达式转换为COUNT(*),因此在运行时检查每行的可为空性COUNT(1)