Count(*) против Count(1) в SQL Server
Заголовок: Разница в производительности между Count(1)
и Count(*)
в SQL Server 2005
Описание проблемы:
Здравствуйте! У меня возник вопрос о использовании Count(1)
по сравнению с Count(*)
в контексте SQL Server 2005. Использует ли кто-нибудь из вас Count(1)
вместо Count(*)
и есть ли заметная разница в производительности между этими двумя подходами? Или это всего лишь устаревшая практика, которая осталась с прошлых времён? Буду благодарен за любые советы и опыт!
5 ответ(ов)
В SQL Server эти операторов выдают одинаковые планы выполнения.
Напротив широко распространенному мнению, в Oracle они тоже.
Функция SYS_GUID()
в Oracle является довольно затратной по вычислениям.
В моей тестовой базе данных t_even
содержит 1,000,000
строк.
Этот запрос:
SELECT COUNT(SYS_GUID())
FROM t_even
выполняется за 48
секунд, поскольку функция должна будет оценить каждое возвращаемое значение SYS_GUID()
, чтобы убедиться, что оно не равно NULL
.
Тем не менее, этот запрос:
SELECT COUNT(*)
FROM (
SELECT SYS_GUID()
FROM t_even
)
выполняется всего за 2
секунды, так как он даже не пытается оценить SYS_GUID()
(несмотря на то, что *
является аргументом для COUNT(*)
).
Это демонстрирует, как может значительно варьироваться производительность запросов в зависимости от того, как они структурированы.
Очевидно, что COUNT(*)
и COUNT(1)
всегда будут возвращать одинаковый результат. Поэтому, если одна из этих операций будет медленнее другой, это, по сути, будет свидетельствовать о наличии бага в оптимизаторе. Поскольку обе формы используются очень часто в запросах, не имеет смысла, чтобы СУБД допускала существование такого бага без исправления. Таким образом, можно предположить, что производительность обеих форм (вероятно) идентична во всех основных СУБД SQL.
В стандарте SQL-92 COUNT(*)
конкретно означает "кардинальность выражения таблицы" (это может быть базовая таблица, представление, производная таблица, CTE и т.д.).
Я думаю, основная идея здесь заключается в том, что COUNT(*)
легко обрабатывается парсером. Использование любого другого выражения требует от парсера проверки, чтобы оно не ссылалось на какие-либо колонки (например, COUNT('a')
, где 'a' — это литерал, и COUNT(a)
, где 'a' — это колонка, могут давать разные результаты).
В том же духе COUNT(*)
легко распознается разработчиком, знакомым со стандартами SQL, что является полезным навыком при работе с несколькими системами управления базами данных (СУБД).
Кроме того, в специальном случае SELECT COUNT(*) FROM MyPersistedTable;
предполагается, что СУБД вероятно будет хранить статистику по кардинальности таблицы.
Таким образом, поскольку COUNT(1)
и COUNT(*)
семантически эквивалентны, я предпочитаю использовать COUNT(*)
.
COUNT(*)
и COUNT(1)
дают один и тот же результат и имеют одинаковую производительность. Оба этих выражения подсчитывают количество строк в результате запроса.
Тем не менее, COUNT(*)
считается более предпочтительным, поскольку он явно указывает на то, что мы хотим подсчитать все строки, независимо от значений в столбцах. В некоторых СУБД COUNT(1)
может восприниматься как подсчет значений, равных 1, но фактически это не ухудшает производительность.
В большинстве случаев использование COUNT(*)
будет являться стандартом, и предпочтительнее с точки зрения читабельности и ясности кода.
В общем, я бы ожидал, что оптимизатор гарантирует отсутствие реальной разницы за исключением каких-то странных крайних случаев.
Как и в случае с любым другим, единственный способ понять — это измерить производительность в ваших конкретных случаях.
Тем не менее, я всегда использовал COUNT(*)
.
Вставка нескольких строк в одном SQL-запросе?
Найти все таблицы, содержащие столбец с указанным именем
Функция против Хранимой процедуры в SQL Server
Сброс начального значения идентификатора после удаления записей в SQL Server
Переименование столбца в SQL Server 2008