Разница между счетом (1) и счетом (*) в оракуле - программирование
Подтвердить что ты не робот

Разница между счетом (1) и счетом (*) в оракуле

Через несколько источников, книг и через asktom я обнаружил, что нет разницы между count(1) и count(*). где-то я нашел count(1) быстрее, чем count(*). Но я действительно не знаю, как это сделать? Что касается, как мне известно, count(*) подсчитывает rowid и count(1) подсчитывает 1 как количество строк. так как rowid имеет 18-значный символ, требуется ли больше времени? Насколько я знаю, размер 2 или 38 не имеет значения для скорости.

Кто-нибудь из вас, пожалуйста, очистите мои сомнения.

4b9b3361

Ответ 1

Я считаю, что 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 |
-----------------------------------------------------------------------------------------

Таким образом, он не только достаточно умен, чтобы знать, что он может использовать индекс для оптимизации этого запроса, но он использует точно такой же план выполнения для разных версий (план имеет значение одно и то же).

Ответ 2

count (1) и count (*) теперь одинаковы для оракула, и в нем используется индекс, если он доступен, и count Nulls тоже. count (1) просто заменяет данные строк на 1, а затем подсчитывает число 1, а count (*) count строк может быть на основе rowids.

Ответ 3

Я думаю, что источником этого слуха является предположение, что база данных должна внутренне расширять * в полный список столбцов, и поэтому замена какого-либо буквального count('Dracula') позволяет избежать этих накладных расходов. Но этого нет, и этого никогда не было. Я впервые услышал об этом вокруг Oracle 6 в 1990 году (другой вариант заключался в том, что вы должны использовать столбец 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) - это дает вам больше нажатий клавиш для ввода и делает вас похожим на тех, кто верит слухам.

Ответ 4

Я протестировал два простых запроса, вычисляющих COUNT(*) или COUNT(1) для 1M строк в Oracle и нескольких других RDBMS, и не нашел никаких отличий в Oracle. Подробности смотрите в этом посте.

Однако в PostgreSQL 11.3 кажется, что COUNT(1) работает примерно на 10% медленнее, потому что PostgreSQL не преобразует выражение в COUNT(*) и, таким образом, проверяет обнуляемость в каждой строке при запуске COUNT(1).