Быстрый способ узнать количество строк таблицы в 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;
740   7  

7 ответов:

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

вместо точно граф (медленно С большой таблицы):

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 х ваш порог (или любое число, которое вы считаете имеет смысл для вашего приложение.)

в зависимости от сложности вашего запроса, это число может становиться все менее и менее точный. Фактически, в моем приложении, когда мы добавили соединения и сложные условия, это стало настолько неточным, что было совершенно бесполезно даже знать, как в пределах 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;

насколько широк текстовый столбец?

с группой по Там не так много вы можете сделать, чтобы избежать сканирования данных (по крайней мере, сканирование индекса).

Я бы рекомендовал:

  1. Если возможно, измените схему, чтобы удалить дублирование текстовых данных. Таким образом, подсчет будет происходить в узком поле внешнего ключа в таблице "много".

  2. альтернативно, создание сгенерированного столбца с хэшем текста, а затем группировка по хэшу колонна. Опять же, это должно уменьшить рабочую нагрузку (сканирование через узкий индекс столбца)

Edit:

ваш исходный вопрос не совсем соответствует вашей редактирование. Я не уверен, что вы знаете, что счетчик, когда он используется с группой 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;

Comments

    Ничего не найдено.