В чем разница между выбором количества (*) и выбором количества (any_non_null_column)?


58

Кажется, я помню, что (на Oracle) есть разница между произнесением select count(*) from any_tableи select count(any_non_null_column) from any_table.

Каковы различия между этими двумя утверждениями, если таковые имеются?

Ответы:


72
  • COUNT (*) будет содержать NULL
  • COUNT (column_or_expression) не будет.

Это означает, что вы COUNT(any_non_null_column)получите то же самое, что и, COUNT(*)конечно, потому что нет значений NULL, которые могли бы вызвать различия.

Как правило, COUNT(*)должно быть лучше, потому что любой индекс может быть использован, потому что COUNT(column_or_expression)не может быть проиндексирован или SARGable

От ANSI-92 (ищите " Scalar expressions 125")

Случай:

a) Если указано COUNT (*), то результатом будет количество элементов T.

b) В противном случае, пусть TX будет таблицей из одного столбца, которая является результатом применения <выражения значения> к каждой строке T и исключения нулевых значений. Если одно или несколько нулевых значений удаляются, то возникает условие завершения: предупреждение - нулевое значение исключается в заданной функции.

Те же правила применяются по крайней мере к SQL Server и Sybase

Примечание. COUNT (1) - это то же самое, что и COUNT (*), потому что 1 является ненулевым выражением.


4
Просто для полноты: Oracle будет использовать сканирование индекса по индексируемому ненулевому столбцу, если count(*)он используется.
a_horse_with_no_name

Я думал, что возможны три варианта COUNT(*), COUNT(<constant>)и COUNT(<column name>)что все три могут иметь префикс ALLили или DISTINCT(по умолчанию, ALLесли не указан). Мне просто интересно, какое выражение можно использовать там, где ты говоришь _or_expression?
понедельник,

2
@onedaywhen COUNT(1)как бесполезный пример, это так же, как COUNT(*). COUNT(CASE WHEN a>b THEN 1 END)в качестве примера, который считает строки, где а> б.
ypercubeᵀᴹ

16

В любой недавней (то есть 8.x + ) версии Oracle они делают то же самое . Другими словами, единственная разница семантическая:

select count(*) from any_table

легко читаемым и очевидным, что вы пытаетесь сделать, и

select count(any_non_null_column) from any_table

труднее читать, потому что

  1. это длиннее
  2. это менее узнаваемо
  3. Вы должны думать о том, any_non_null_columnдействительно ли применяется какnot null

Короче говоря, используйтеcount(*)



1

В книге Руководство по сертификационному экзамену Oracle8i для сертифицированных профессиональных DBA (ISBN 0072130601) на стр. 78 говорится, что COUNT (1) будет на самом деле работать быстрее, чем COUNT (*), потому что определенные механизмы задействуются для проверки словаря данных на предмет обнуляемости каждого столбца (или по крайней мере, первый столбец с ненулевым значением) при использовании COUNT (*) . COUNT (1) обходит эти механизмы.

MySQL читы для «SELECT COUNT (1) на tblname;» в таблицах MyISAM, читая заголовок таблицы для количества таблиц. InnoDB считает каждый раз.

Чтобы проверить, будет ли COUNT (1) работать быстрее, чем COUNT (*), без учета базы данных, просто выполните следующее и оцените время выполнения для себя:

SELECT COUNT(1) FROM tblname WHERE 1 = 1;
SELECT COUNT(*) FROM tblname WHERE 1 = 1;
SELECT COUNT(column-name) FROM tblname WHERE 1 = 1;

Это позволяет функции COUNT работать на игровом поле одного уровня независимо от механизма хранения или RDBMS.


8
Руководство по экзамену не так. В Oracle count (*) = count (1) (по крайней мере, после версии 7). См. Asktom.oracle.com/pls/asktom/… (на который уже ссылается @JackPDouglas)
Ли Риффель

3
Интересно. COUNT (*) не должен проверять столбцы вообще согласно спецификации ANSI. Был задан вопрос о SO для SQL Server некоторое время назад тоже stackoverflow.com/questions/1221559/count-vs-count1/…
gbn

@gbn, @Leigh Riffel, @bernd_k Спасибо, что присоединились и напомнили мне прочитать и узнать больше, тем более, что я некоторое время не работал с Oracle.
RolandoMySQLDBA
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.