@mkone112
Начинающий питонист.

Как быстро и с минимальной погрешностью подсчитать число записей в таблице с миллиардами записей?

Работаю над проектом на django, в качестве бд используется postgres. Бд содержит тысячи таблиц, многие из таблиц могут содержать десятки миллиардов записей.
Проблема - count() выполняется по полчаса.
Я использовал приблизительный подсчет записей вроде:
SELECT reltuples FROM pg_class WHERE relname = "table"

Но результат в 300 раз меньше реального - это слишком большая погрешность.
Есть ли способ, быстро подсчитать число записей, без уменьшения скорости записи?
  • Вопрос задан
  • 1313 просмотров
Пригласить эксперта
Ответы на вопрос 6
BojackHorseman
@BojackHorseman
...в творческом отпуске...
не отталкивайтесь в логике от count, который к тому же постоянно меняется. вам не все равно сколько там тех записей? главное - достучаться по PK быстро до одной конкретной.

нет запроса - нет проблемы ©
Ответ написан
@krasszen2
житель земли
Не факт, но может это поможет? А еще комменты там почитай.
Ответ написан
@BorisKorobkov
Web developer
SELECT reltuples FROM pg_class WHERE relname = "table"

Это и есть самый быстрый способ.
Погрешность можно (нужно) уменьшить, если сделать VACUUM или ANALYZE. Подробнее см. https://www.postgresql.org/docs/9.2/row-estimation...
Ответ написан
romesses
@romesses
Backend инженер
TimescaleDB

Похоже, что вам нужна TimescaleDB - оптимизированная СУБД для временных серий.

Как раз вашу проблему должен решить данный запрос (в рамках использования TimescaleDB):
SELECT h.schema_name,
    h.table_name,
    h.id AS table_id,
    h.associated_table_prefix,
    row_estimate.row_estimate
   FROM _timescaledb_catalog.hypertable h
     CROSS JOIN LATERAL ( SELECT sum(cl.reltuples) AS row_estimate
           FROM _timescaledb_catalog.chunk c
             JOIN pg_class cl ON cl.relname = c.table_name
          WHERE c.hypertable_id = h.id
          GROUP BY h.schema_name, h.table_name) row_estimate
ORDER BY schema_name, table_name;

https://github.com/timescale/timescaledb/issues/525

И заодно проверьте другие TSDB.


Добавлено
Попробуйте через трюк с EXPLAIN:
CREATE FUNCTION row_estimator(query text) RETURNS bigint
   LANGUAGE plpgsql AS
$$DECLARE
   plan jsonb;
BEGIN
   EXECUTE 'EXPLAIN (FORMAT JSON) ' || query INTO plan;
 
   RETURN (plan->0->'Plan'->>'Plan Rows')::bigint;
END;$$;

https://www.cybertec-postgresql.com/en/postgresql-...
https://wiki.postgresql.org/wiki/Count_estimate
https://www.citusdata.com/blog/2016/10/12/count-pe...
Ответ написан
Не знаю насколько адекватный вариант, но что если в принципе отвязаться от подсчёта из бд, а привязаться к созданиям и удалениям самих данный, типо если запись успешно добавлена то мы в отдельной табличке, созданной специально для хранения количества записей делаем инкремент числа, а если удаляем то декремент
Ответ написан
PretorDH
@PretorDH
HTML5, CSS3, PHP, JS - люблю в чистом виде.
Давайте анализировать. Гугл не в помощь в вашем случае.

How to Define an Auto Increment Primary Key in Pos...

При таких больших таблицах важно чтобы была непрерывность индекса.
Это значит, что удалять записи из таких таблиц дурной тон. А из этого следует, что количество записей равно значению следующего индекса. Значит достаточно узнать значение индекса.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы