Быстрый способ узнать количество строк таблицы в PostgreSQL
мне нужно знать количество строк в таблице, чтобы вычислить процент. Если общее количество больше некоторой предопределенной константы, я буду использовать постоянное значение. В противном случае я буду использовать фактическое количество строк.
Я могу использовать SELECT count(*) FROM table
. Но если мое постоянное значение 500,000 и 5,000,000,000 строк в моей таблице, подсчет всех строк будет тратить много времени.
можно ли прекратить подсчет, как только мое постоянное значение превзошли?
мне нужно точное количество строк только до тех пор, пока оно ниже заданного предела. В противном случае, если количество выше предела, я использую предельное значение и хочу получить ответ как можно быстрее.
что-то вроде этого:
SELECT text,count(*), percentual_calculus()
FROM token
GROUP BY text
ORDER BY count DESC;
7 ответов
подсчет строк в большой таблицы, как известно, медленные в PostgreSQL. Чтобы получить точное число, он должен сделать полный подсчет строк из-за природы MVCC. Есть способ ускорить это драматически если число не должны быть точно как это, кажется, в вашем случае.
вместо точно count (медленно С большой таблицы):
SELECT count(*) AS exact_count FROM myschema.mytable;
вы получаете близкую оценку, как это (очень быстро):
SELECT reltuples::bigint AS estimate FROM pg_class where relname='mytable';
насколько близка оценка зависит от того, выполняете ли вы ANALYZE
Я сделал это один раз в приложении postgres, запустив:
EXPLAIN SELECT * FROM foo;
затем исследуя выход с регулярным выражением или аналогичной логикой. Для простого выбора * первая строка вывода должна выглядеть примерно так:
Seq Scan on uids (cost=0.00..1.21 rows=8 width=75)
можно использовать rows=(\d+)
значение как приблизительная оценка количества строк, которые будут возвращены, тогда только фактическое SELECT COUNT(*)
если оценка, скажем, меньше 1.5 x ваш порог (или любое число, которое вы считаете имеет смысл для вашего приложение.)
в зависимости от сложности вашего запроса, это число может становиться все менее и менее точный. На самом деле, в моем приложении, когда мы добавили соединения и сложные условия, это стало настолько неточным, что было совершенно бесполезно, даже знать, как в пределах 100, сколько строк мы бы вернули, поэтому нам пришлось отказаться от этой стратегии.
но если ваш запрос достаточно прост, что Pg может предсказать в пределах разумной погрешности, сколько строк он вернет, он может сработать на вас.
в Oracle вы можете использовать rownum
чтобы ограничить количество возвращаемых строк. Я предполагаю, что подобная конструкция существует и в других SQLs. Таким образом, в приведенном примере вы можете ограничить количество строк, возвращаемых 500001, и применить count(*)
затем:
SELECT (case when cnt > 500000 then 500000 else cnt end) myCnt
FROM (SELECT count(*) cnt FROM table WHERE rownum<=500001)
вы можете получить количество по приведенному ниже запросу (без * или любых имен столбцов).
select from table_name;
насколько широк текстовый столбец?
с группой по не так много вы можете сделать, чтобы избежать сканирования данных (по крайней мере, сканирование индекса).
Я бы рекомендовал:
Если возможно, измените схему, чтобы удалить дублирование текстовых данных. Таким образом, подсчет будет происходить в узком поле внешнего ключа в таблице "много".
альтернативно, создание сгенерированного столбца с хэшем текста, а затем группировка по хэшу колонна. Опять же, это уменьшает рабочую нагрузку (сканирование через узкий индекс столбца)
Edit:
ваш исходный вопрос не совсем соответствует вашей редактирование. Я не уверен, знаете ли вы, что COUNT при использовании с GROUP BY возвращает количество элементов в группе, а не количество элементов во всей таблице.
для SQL Server (2005 или выше) быстрый и надежный метод:
SELECT SUM (row_count)
FROM sys.dm_db_partition_stats
WHERE object_id=OBJECT_ID('MyTableName')
AND (index_id=0 or index_id=1);
подробности о sys.dm_db_partition_stats объясняются в MSDN
запрос добавляет строки из всех частей (возможно) секционированной таблицы.
index_id=0-неупорядоченная таблица (куча), а index_id=1-упорядоченная таблица (кластеризованный индекс)
еще более быстрые (но ненадежные) методы детализированы здесь.
Вы можете использовать ниже запроса, чтобы найти количество строк.
используя pg_class:
SELECT reltuples::bigint AS EstimatedCount
FROM pg_class
WHERE oid = 'public.TableName'::regclass;
использование pg_stat_user_tables:
SELECT
schemaname
,relname
,n_live_tup AS EstimatedCount
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC;