проверка работоспособности: количество (*) против количества (pkColumn) - PullRequest
2 голосов
/ 14 сентября 2011

Сегодня мой босс сказал мне использовать count(pkColumn) вместо count(*), сказав, что это будет быстрее.Я почти уверен, что это не так, но я не администратор баз данных, а разработчик Java, поэтому я хотел проверить.

Я выполнил несколько планов запросов:

EXPLAIN SELECT COUNT(*) FROM "Foo";
EXPLAIN SELECT COUNT("FooUID") FROM "Foo";
EXPLAIN SELECT COUNT(1) FROM "Foo";

Срезультаты:

Aggregate  (cost=1421.01..1421.02 rows=1 width=0)
  ->  Seq Scan on "Foo"  (cost=0.00..1296.81 rows=49681 width=0)

Aggregate  (cost=1421.01..1421.02 rows=1 width=16)
  ->  Seq Scan on "Foo"  (cost=0.00..1296.81 rows=49681 width=16)

Aggregate  (cost=1421.01..1421.02 rows=1 width=0)
  ->  Seq Scan on "Foo"  (cost=0.00..1296.81 rows=49681 width=0)

Они кажутся одинаковыми.Может кто-то просто подтвердить, что я прав по этому поводу?Я понимаю, что это обсуждалось для других языков, но PostgreSQL по-разному обрабатывает COUNT, и я не смог найти эквивалентный вопрос PostgreSQL.

Обратите внимание, что "FooUID" никогда не будет NULL.

РЕДАКТИРОВАТЬ: с использованием версии 9.0.4

Ответы [ 3 ]

6 голосов
/ 14 сентября 2011

Ваш босс введен в заблуждение (в лучшем случае).

Да, PostgreSql (по крайней мере, те, которые я использовал, до 8.1) действительно обрабатывает count немного по-другому, поскольку ему нужно перейти к реальной таблице, чтобы получить некоторую информацию, а не просто использовать только индекс MVCC , он хранит «мягкую» информацию об удалении в таблице, поэтому необходимо извлечь каждую строку, чтобы увидеть, была ли она удалена, но еще не удалена из индекса).

Но он должен это делать независимо от того, используете ли вы * или pk_column для подсчета. Преимущество использования * состоит в том, что СУБД может свободно выбирать любой ненулевой столбец для счетчика, что может привести к меньшему количеству дискового ввода-вывода для обработки индекса.

Если ваш начальник беспокоится о производительности, есть несколько возможных «хитростей», которые вы можете использовать.

Во-первых, если вас интересует только существование строк, а не число , , вы можете использовать код изменения, например:

select count(*) into myCount from myTable where myCondition;
if myCount > 0 then
    do something
end if;

в

if exists ( select * from myTable where myCondition ) then
    do something
end if;

Во-вторых, вы можете использовать триггеры insert и delete, которые поддерживают два счетчика в отдельной таблице для добавленных строк и удаленных строк. Затем вы можете рассчитать количество строк, просто вычитая одно из другого. Использование двух отдельных счетчиков предотвращает сериализацию в операциях вставки / удаления, но это все еще является огромным препятствием и, вероятно, не требуется для огромного числа случаев.

Вам также необходимо периодически уменьшать счетчики (например, изменить 1000 inserts + 200 deletes на 800 inserts and 0 deletes).

В-третьих, вы можете получить оценку количества строк (на основе последней операции анализа), используя:

select reltuples from pg_class where relname = 'myTable';
1 голос
/ 14 сентября 2011

В PostgreSQL:

  • count(*) равно count(PK)

    Как сказал Богемный , существует небольшая задержка в переводе* в поле;однако также существует задержка в легитимизации PK в качестве допустимого поля.Несмотря на это, они являются незначительными хитами производительности.

Дополнительное чтение:

Документы PostgreSQL :

  • Примечание. Пользователи, привыкшие работать с другими системами управления базами данных SQL, могут быть разочарованы производительностьюсчитать агрегат, когда он применяется ко всей таблице.Запрос типа:

    SELECT count(*) FROM sometable;

    будет выполняться PostgreSQL с использованием последовательного сканирования всей таблицы.

1 голос
/ 14 сентября 2011

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

Это "преимущество" настолько незначительно по сравнению с вызванным снижением читабельности, что лишает базу данных возможности оптимизировать ваши намерения с помощью какого-либо другого механизма (например,считать индексированный столбец и, таким образом, выполнять поиск только по индексу).

Использовать count(*).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...