Как известно, подсчет строк в больших таблицах в PostgreSQL выполняется медленно. Чтобы получить точное число, он должен выполнить полный подсчет строк из-за природы MVCC . Есть способ значительно ускорить это, если подсчет не должен быть точным, как в вашем случае.
Вместо точного подсчета ( медленно с большими таблицами):
SELECT count(*) AS exact_count FROM myschema.mytable;
Вы получите такую близкую оценку ( очень быстро ):
SELECT reltuples::bigint AS estimate FROM pg_class where relname='mytable';
Насколько близка оценка, зависит от того, ANALYZE
достаточно ли вы бегаете . Обычно это очень близко.
См. FAQ по PostgreSQL Wiki .
Или специальная вики-страница для подсчета (*) производительности .
Еще лучше
В статье в PostgreSQL Wiki это было немного неаккуратно . Он игнорировал возможность того, что в одной базе данных может быть несколько таблиц с одинаковым именем - в разных схемах. Чтобы учесть это:
SELECT c.reltuples::bigint AS estimate
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = 'mytable'
AND n.nspname = 'myschema'
Или еще лучше
SELECT reltuples::bigint AS estimate
FROM pg_class
WHERE oid = 'myschema.mytable'::regclass;
Быстрее, проще, безопаснее, элегантнее. См. Руководство по типам идентификаторов объектов .
Используйте to_regclass('myschema.mytable')
в Postgres 9.4+, чтобы избежать исключений для недопустимых имен таблиц:
SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);
Как и прокомментировал @a_horse , недавно добавленное предложение для SELECT
команды может быть полезно, если статистика pg_class
по какой-то причине недостаточно актуальна. Например:
- Нет
autovacuum
бега.
- Сразу после большого
INSERT
или DELETE
.
TEMPORARY
таблицы (которые не покрываются autovacuum
).
Это только смотрит на случайный выбор n % ( 1
в примере) блоков и подсчитывает строки в нем. Более крупный образец увеличивает стоимость и уменьшает ошибку, ваш выбор. Точность зависит от большего количества факторов:
- Распределение размера строки. Если данный блок содержит более широкие, чем обычно, строки, счетчик меньше обычного и т. Д.
- Мертвые кортежи или
FILLFACTOR
занимаемое пространство на блок. При неравномерном распределении по таблице оценка может быть неверной.
- Общие ошибки округления.
В большинстве случаев оценка pg_class
будет быстрее и точнее.
Ответ на актуальный вопрос
Во-первых, мне нужно знать количество строк в этой таблице, если общее количество больше некоторой предопределенной константы,
И будь это ...
... возможно в тот момент, когда счетчик передаст мое постоянное значение, он остановит счет (и не дожидается окончания счета, чтобы сообщить, что счетчик строк больше).
Да. Вы можете использовать подзапрос сLIMIT
:
SELECT count(*) FROM (SELECT 1 FROM token LIMIT 500000) t;
Postgres фактически перестает считать сверх заданного лимита, вы получаете точное и текущее количество до n строк (500000 в примере) и n в противном случае. Однако не так быстро, как предполагалось pg_class
.