Подсчет строк в больших таблицах, как известно, медленен в PostgreSQL.Чтобы получить точное число, необходимо выполнить полный подсчет строк из-за природы MVCC .Есть способ резко ускорить это , если счет не должен быть точным , как это кажется в вашем случае.
Вместо того, чтобы точный счет ( медленный с большими таблицами):
SELECT count(*) AS exact_count FROM myschema.mytable;
Вы получаете близкую оценку как это ( очень быстро ):
SELECT reltuples::bigint AS estimate FROM pg_class where relname='mytable';
Насколько близка оценка, зависит от того, достаточно ли вы наберете ANALYZE
.Обычно это очень близко.
См. FAQ по вики PostgreSQL .
или выделенную вики-страницу для подсчета (*) производительности .
Еще лучше
Статья в Вики PostgreSQL - это , была немного небрежно .При этом игнорируется возможность того, что в одной базе данных может быть несколько таблиц с одним и тем же именем - в разных схемах.Чтобы объяснить это:
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
.