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



@mkone112

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

Но результат в 300 раз меньше реального — это слишком большая погрешность.
Есть ли способ, быстро подсчитать число записей, без уменьшения скорости записи?


Решения вопроса 0


Ответы на вопрос 6



@BojackHorseman

не отталкивайтесь в логике от count, который к тому же постоянно меняется. вам не все равно сколько там тех записей? главное — достучаться по PK быстро до одной конкретной.

нет запроса — нет проблемы ©



@krasszen2

Не факт, но может это поможет? А еще комменты там почитай.



@BorisKorobkov

SELECT reltuples FROM pg_class WHERE relname = «table»

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



@romesses

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…



@Mugenzo

Не знаю насколько адекватный вариант, но что если в принципе отвязаться от подсчёта из бд, а привязаться к созданиям и удалениям самих данный, типо если запись успешно добавлена то мы в отдельной табличке, созданной специально для хранения количества записей делаем инкремент числа, а если удаляем то декремент



@PretorDH

Давайте анализировать. Гугл не в помощь в вашем случае.

How to Define an Auto Increment Primary Key in Pos…

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *