Подтвердить что ты не робот

Как ускорить подсчет строк в таблице PostgreSQL?

Нам нужно подсчитать количество строк в таблице PostgreSQL. В нашем случае никаких условий не требуется, и было бы вполне приемлемо получить оценку строки, если бы это значительно улучшило скорость запроса.

В принципе, мы хотим, чтобы select count(id) from <table> выполнялся как можно быстрее, даже если это подразумевает не получение точных результатов.

Спасибо! Любые предложения будут оценены!

4b9b3361

Ответ 1

Для быстрой оценки:

SELECT reltuples FROM pg_class WHERE oid = 'my_schema.my_table'::regclass;

Это выше запросов, представленных до сих пор, включая рекомендации в Postgres Wiki при медленном подсчете. (Я обновил это к настоящему времени.):
relname не является уникальным в pg_class. В нескольких схемах базы данных может быть несколько таблиц с тем же relname. Это регулярно в моих установках.

И запрос на pg_stat_user_tables на 500x медленнее, потому что это представление на пару таблиц.

Если вы не присваиваете схему имени таблицы, приведение к regclass наблюдает текущий search_path, чтобы выбрать лучший матч. И если таблица не существует (или не может быть видна) в любой из схем в search_path, вы получите сообщение об ошибке.

Подробная информация о Типы идентификаторов объектов в руководстве.

Связанный ответ с новыми параметрами:

Ответ 2

Граф медленный для больших таблиц, поэтому вы можете получить близкую оценку следующим образом:

SELECT reltuples::bigint AS estimate 
FROM pg_class 
WHERE relname='tableName';

и его чрезвычайно быстрый результат не является плавающей, но все еще близкой оценкой.

  • reltuples - это столбец из таблицы pg_class, он содержит данные о количестве строк в таблице. Это только оценка, используемая планировщиком. Она обновляется с помощью VACUUM, ANALYZE и нескольких команд DDL таких как CREATE INDEX "(руководство)
  • Каталог pg_class каталогизирует таблицы и большинство всего остального, которые имеют столбцы или в противном случае похожи на таблицу. Это включает в себя индексы (но см. Также pg_index), последовательности, виды, составные типы и некоторые виды специальных отношений (вручную).
  • "Почему" SELECT count (*) FROM bigtable, "slow?": http://wiki.postgresql.org/wiki/FAQ#Why_is_.22SELECT_count.28.2A.29_FROM_bigtable.3B.22_slow.3F

Ответ 3

Помимо запуска COUNT() в индексированном поле (которое, надеюсь, "id" ), следующая лучшая вещь - фактически кэшировать количество строк в некоторой таблице с помощью триггера на INSERT. Естественно, вы будете проверять кеш.

В приближении вы можете попробовать это (от https://wiki.postgresql.org/wiki/Count_estimate):

select reltuples from pg_class where relname='tablename';

Ответ 4

Вы можете получить оценку из системной таблицы "pg_stat_user_tables".

select schemaname, relname, n_live_tup 
from pg_stat_user_tables 
where schemaname = 'your_schema_name'
and relname = 'your_table_name';

Ответ 5

Вы можете запросить точное значение счета в таблице, просто используя триггер ПОСЛЕ ВСТАВКИ ИЛИ УДАЛИТЬ Что-то вроде этого

CREATE TABLE  tcounter(id serial primary key,table_schema text, table_name text, count serial);

insert into tcounter(table_schema, table_name,count) select 'my_schema', 'my_table', count(*) from my_schema.my_table;

и используйте триггер

CREATE OR REPLACE FUNCTION ex_count()
RETURNS trigger AS
$BODY$
BEGIN
    IF (TG_OP='INSERT') THEN
      UPDATE tcounter set count = count + 1 where table_schema = TG_TABLE_SCHEMA::TEXT and table_name = TG_TABLE_NAME::TEXT;
    ELSIF  (TG_OP='DELETE') THEN
      UPDATE tcounter set count = count - 1 where table_schema = TG_TABLE_SCHEMA::TEXT and table_name = TG_TABLE_NAME::TEXT;
    END IF;
RETURN NEW;
END$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

CREATE TRIGGER tg_counter  AFTER INSERT OR DELETE
  ON my_schema.my_table  FOR EACH ROW  EXECUTE PROCEDURE ex_count();

И попросите счет

select * from tcounter where table_schema =  'my_schema' and table_name = 'my_table'

это означает, что вы выбрали count (*) один раз для инициализации первой записи

Ответ 6

Если ваша база данных мала, вы можете получить оценку всех ваших таблиц, например, @mike-sherrill-cat-отзыв. Эта команда будет перечислять все таблицы.

SELECT schemaname,relname,n_live_tup 
FROM pg_stat_user_tables 
ORDER BY n_live_tup DESC;

Результат будет примерно таким:

 schemaname |      relname       | n_live_tup
------------+--------------------+------------
 public     | items              |      21806
 public     | tags               |      11213
 public     | sessions           |       3269
 public     | users              |        266
 public     | shops              |        259
 public     | quantities         |         34
 public     | schema_migrations  |         30
 public     | locations          |          8
(8 rows)