powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / select count(*) from t - как быстрее получить прибл.к-во
38 сообщений из 38, показаны все 2 страниц
select count(*) from t - как быстрее получить прибл.к-во
    #34757609
Winnipuh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно ли посчитать к-во записей быстро, пусть не точное, приблизительное, скажем если там 11 234 567, а я получу 11 100 000, то это меня устроит, важно масштаб и скорость
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34757638
untitled
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SELECT reltuples FROM pg_class WHERE relname = 'tablename';
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34757660
Winnipuh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
untitledSELECT reltuples FROM pg_class WHERE relname = 'tablename';

шайтан! :-)

в чем "приблизительность" количества? у меня совпало сейчас, но юзеров нету.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34757677
untitled
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
это значение, которое было вычислено после analyze
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34757704
Winnipuh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
untitledэто значение, которое было вычислено после analyze

т.е. это будет не приблизительное значение, оно может отличаться на порядки, в зависимости от того как давно выполнялся analyze.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34757749
untitled
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
теоретически да.

но при включенном автовакууме это значение всегда будет более-менее правильным.
даже если автовакуума нет, то хорошим решением будет раз в сутки делать vacuum analyze, что, в том числе, обновит эту таблицу с количеством записей.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34757786
assa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
если нужно именно то, что написано - т.е. каунты _без условий_ - то кажется LeXa NalBat (мои извинения, ежли путаю) неоднократно рекомендовал вести свои таблички на триггерах. Все упирается в соотношение цена(решения)/частота пользования.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34757911
Winnipuh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
assaесли нужно именно то, что написано - т.е. каунты _без условий_ - то кажется LeXa NalBat (мои извинения, ежли путаю) неоднократно рекомендовал вести свои таблички на триггерах. Все упирается в соотношение цена(решения)/частота пользования.

да, понимаю, но для таблицы с 10 млн записей триггеры дороговаты будут...
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34758026
Rastafarra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
между прочим один умный человек мне советовал делать не count(*), а count(primary_key) :)

обосновывал он свою позицию использованием индексированного поля и скоростью работы с ним.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34758138
Nick Gazaloff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Rastafarraмежду прочим один умный человек мне советовал делать не count(*), а count(primary_key) :)

обосновывал он свою позицию использованием индексированного поля и скоростью работы с ним.

Сделайте explain и убедитесь, что разницы никакой.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34758300
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nick Gazaloff Rastafarraмежду прочим один умный человек мне советовал делать не count(*), а count(primary_key) :)

обосновывал он свою позицию использованием индексированного поля и скоростью работы с ним.Сделайте explain и убедитесь, что разницы никакой.Да, даже скорее всего выполнение через IndexScan будет медленнее, чем SeqScan, потому что при IndexScan постгрес все равно будет залезать в таблицу.

Но кажется тут проводили тесты, что count(1) немного быстрее из-за меньшей ширины выбираемых полей.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34758751
assa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Winnipuhда, понимаю, но для таблицы с 10 млн записей триггеры дороговаты будут...не понял. если вы в триггере напишете "селект каунт()"- то да. а если триггера - "дифференциальные" - то цена зависит не от колич-ва записей, а от частоты вставки/удаления. Нет?
Т.е. надо сравнить возрастание нагрузки при вставке/удалении с частотой выполнения "селект-каунтов". Вот на табличку с ежедневной массовой заливкой и очисткой я бы поостерегся, что да, то да.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34758944
alex_v13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
count любого поля будет все равно SeqScan из-за такой реализации в ПГ агрегатных ф-й.

Winnipuh
Если в таблице есть уникальный числовой ключ типа генерируемы по sequence, то max(key) даст точное количество записей и будет пользовать индекс по этому полю. Если нет, то только через tuples
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34759020
Winnipuh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_v13count любого поля будет все равно SeqScan из-за такой реализации в ПГ агрегатных ф-й.

Winnipuh
Если в таблице есть уникальный числовой ключ типа генерируемы по sequence, то max(key) даст точное количество записей и будет пользовать индекс по этому полю. Если нет, то только через tuples

вопрос:
если в таблице 1000 записей,
max(key) = 1000

потом удалили 900,
max(key) = 1000

?
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34759069
assa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Winnipuh alex_v13count любого поля будет все равно SeqScan из-за такой реализации в ПГ агрегатных ф-й.

Winnipuh
Если в таблице есть уникальный числовой ключ типа генерируемы по sequence, то max(key) даст точное количество записей и будет пользовать индекс по этому полю. Если нет, то только через tuples

вопрос:
если в таблице 1000 записей,
max(key) = 1000

потом удалили 900,
max(key) = 1000

?гм. вот можно например вести таблицу вообще без удалений (и апдейтов) (т.е. полный аудит внутри самой себя - все лежит внутри. есть 2 поля- "ключа" - 1 - "эффективный", и 2-й - собственно счетчик всего), тогда предложенное alex_v13 вполне сработает. но как же аккуратно надо все расписывать (через обновляемые вью - наипростейшее решение).
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34759073
untitled
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
можно создать два сиквенса - количество внесенных и удаленных, и брать разницу между ними, но лучше сделать отдельную таблицу для статистики и изменять при помощи триггеров в ней значения. этот подход хорош тем, что можно одновременно вести подсчет по различным заранее известным критериям.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34759084
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_v13count любого поля будет все равно SeqScan из-за такой реализации в ПГ агрегатных ф-й.
Код: plaintext
1.
2.
3.
4.
create table t1 ( id integer primary key );
insert into t1 select generate_series( 1 , 1000 );
analyze t1;
explain select count(*) from t1 where id between  100  and  200 ;
drop table t1;
Код: plaintext
1.
2.
3.
4.
5.
                                QUERY PLAN
--------------------------------------------------------------------------
 Aggregate  (cost= 4 . 85 .. 4 . 86  rows= 1  width= 0 )
   ->  Index Scan using t1_pkey on t1  (cost= 0 . 00 .. 4 . 60  rows= 100  width= 0 )
         Index Cond: ((id >=  100 ) AND (id <=  200 ))
( 3  rows)
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34759103
Winnipuh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
untitledможно создать два сиквенса - количество внесенных и удаленных, и брать разницу между ними, но лучше сделать отдельную таблицу для статистики и изменять при помощи триггеров в ней значения. этот подход хорош тем, что можно одновременно вести подсчет по различным заранее известным критериям .

надо подумать, что будет в случае одновременно активно работающих 100 юзерах
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34759206
untitled
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Winnipuh
надо подумать, что будет в случае одновременно активно работающих 100 юзерах

ну понятно что сначала нужно выяснить необходимость этого. если требуется выводить что-то вроде "на нашем сайте больше 5000 зарегистрированных пользователей" то вполне достаточно брать результаты analyze и не заморачиваться )
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34759386
alex_v13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LeXa NalBat

Это такой план на 8.2.4 ?

У меня на 8.1.3 таблички по 50 млн записей со всеми ииндексами, но такой план ни-ни.

Winnipuh
При активной работе пользователей приводящей с частым обновлениям данных в таблицах уменьшение интервала автовакума сильно улучшает общую картину с производительность, а также reltuples становится сильно ближе действительному числу записей. Тот метод который я предожил содержит ряд условностей (выше о них написали) и нужен только если нужно именно точное значение числа записей.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34760221
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_v13Это такой план на 8.2.4 ?

У меня на 8.1.3 таблички по 50 млн записей со всеми ииндексами, но такой план ни-ни.8.1.9
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34761213
Nick Gazaloff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alex_v13 LeXa NalBat

Это такой план на 8.2.4 ?

У меня на 8.1.3 таблички по 50 млн записей со всеми ииндексами, но такой план ни-ни.



1. У LeXa явно стоит enable_seqscan=false.
2. В данном случае подобный план ничего не улучшает. рекомендую сравнить время выполнения запроса с WHERE (выставив условие, в которое заведомо попадает вся таблица) и без него. Без WHERE будет быстрее.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34761315
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nick Gazaloff1. У LeXa явно стоит enable_seqscan=false.нет

Nick Gazaloff2. В данном случае подобный план ничего не улучшает.улучшает
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
                                                      QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost= 4 . 85 .. 4 . 86  rows= 1  width= 0 ) (actual time= 0 . 501 .. 0 . 503  rows= 1  loops= 1 )
   ->  Index Scan using t1_pkey on t1  (cost= 0 . 00 .. 4 . 60  rows= 100  width= 0 ) (actual time= 0 . 018 .. 0 . 278  rows= 101  loops= 1 )
         Index Cond: ((id >=  100 ) AND (id <=  200 ))
 Total runtime:  0 . 555  ms
( 4  rows)

                                              QUERY PLAN
-------------------------------------------------------------------------------------------------------
 Aggregate  (cost= 21 . 25 .. 21 . 26  rows= 1  width= 0 ) (actual time= 0 . 837 .. 0 . 839  rows= 1  loops= 1 )
   ->  Seq Scan on t1  (cost= 0 . 00 .. 21 . 00  rows= 100  width= 0 ) (actual time= 0 . 044 .. 0 . 610  rows= 101  loops= 1 )
         Filter: ((id >=  100 ) AND (id <=  200 ))
 Total runtime:  0 . 883  ms
( 4  rows)

Nick Gazaloffрекомендую сравнить время выполнения запроса с WHERE (выставив условие, в которое заведомо попадает вся таблица) и без него. Без WHERE будет быстрее.зачем нужно условие where, в которое попадает вся таблица? конечно в этом случае без where будет быстрее.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34762825
Nick Gazaloff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А зачем нужно считать строки с 100-й по 200-ю?

И не надо говорить, что count здесь использует индекс. Индекс использует WHERE.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34763605
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nick GazaloffА зачем нужно считать строки с 100-й по 200-ю?Чтобы узнать кол-во строк в таблице, удовлетворяющих некоторому условию.

Например, кол-во моделей сотовых телефонов в товарном каталоге: "where category_id='mobile'".

Nick GazaloffИ не надо говорить, что count здесь использует индекс. Индекс использует WHERE.Я бы не сказал, что "count использует индекс" и "индекс использует WHERE" - понятные и математически точные формулировки.

Я привел пример опровеграющий утверждение alex_v13 "count любого поля будет все равно SeqScan из-за такой реализации в ПГ агрегатных ф-й". На словах это опровержение сформулировал бы так: для вычисления count постгрес может использовать план отличный от SeqScan, причем это даст выигрыш в скорости выполнения запроса.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34763911
alex_v13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LeXa NalBat
По видимому, разработчики ПГ наконец услышали глас юзеров своей базульки и таки научили планировщик таким элементарным финтам, как использование существующего primary key для count.

Я только пока не могу перебраться на версию старше 8.1.3 - импорт/экспорт базы в ~100 ГБ с последующим vacuum analyze это дофига времени... Бизнес не ждет. До нового года откладываю.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34765096
Andrey Daeron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_v13 LeXa NalBat
По видимому, разработчики ПГ наконец услышали глас юзеров своей базульки и таки научили планировщик таким элементарным финтам, как использование существующего primary key для count.


Попробую сформулировать максимально математично.
Для отработки count() PG должен просмотреть ВСЕ записи попадающие под условие count().
Если эти записи целесообразно получать из индекса (например условие в WHERE), то он может исопльзоться, если нет (SELECT count(*) FROM my_big_table_gigi) - то будет SEQSCAN.
В любом случае, будет проверена КАЖДАЯ строчка. И сама аггрегатная функция count() не может использовать индекс. Он может быть использован только для получения строк. Аггрегатные функция max/min - могут использовать индекс.

Напомню, в индексе PG нет условий видимости записи для текущей транзакции, как следствие - индекс не может использоваться для определения точного количества строк. Что не мешает использовать его для других, не связанных с подсчетом строк задач в рамках этого же запроса.

ЗЫ Вроде похоже на правду
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34765247
alex_v13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Теория-то понятна и очевидна: я же написал "использование существующего primary key для count", а не "count по индексу" :) Так что все справедливо.
Но вот 8.1.3 для count по таблицам любого размера выдает у меня SeqScan, в то время как 8.2.4 таки выдает IndexScan.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34765457
Andrey Daeron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_v13Теория-то понятна и очевидна: я же написал "использование существующего primary key для count", а не "count по индексу" :) Так что все справедливо.
Но вот 8.1.3 для count по таблицам любого размера выдает у меня SeqScan, в то время как 8.2.4 таки выдает IndexScan.
Ничего не понял :( стихи?

провел тест уважаемого LeXa NalBat :

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
Welcome to psql  8 . 1 . 4 , the PostgreSQL interactive terminal.
test=# explain select count(*) from t1 where id between  100  and  200 ;
                                QUERY PLAN
--------------------------------------------------------------------------
 Aggregate  (cost= 4 . 85 .. 4 . 86  rows= 1  width= 0 )
   ->  Index Scan using t1_pkey on t1  (cost= 0 . 00 .. 4 . 60  rows= 100  width= 0 )
         Index Cond: ((id >=  100 ) AND (id <=  200 ))
( 3  rows)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
Welcome to psql  8 . 2 . 4 , the PostgreSQL interactive terminal.
test=# explain select count(*) from t1 where id between  100  and  200 ;
                                QUERY PLAN
---------------------------------------------------------------------------
 Aggregate  (cost= 10 . 50 .. 10 . 51  rows= 1  width= 0 )
   ->  Index Scan using t1_pkey on t1  (cost= 0 . 00 .. 10 . 25  rows= 100  width= 0 )
         Index Cond: ((id >=  100 ) AND (id <=  200 ))
( 3  rows)

ну и в чем разницо?
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34765561
alex_v13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Возможно дело в специфике моей базы - маленькие таблицы с большим количеством UPDATE и очень большие с массовыми INSERT - т.е. или много версий записей или много данных не влезающих в память - понятно, что планировщик выбирает SeqScan.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34765573
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrey Daeronну и в чем разницо?OFFTOPIC

cost=4.85..4.86

cost=10.50..10.51

8.2.4 в два раза медленнее :-)
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34765585
alex_v13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А 8.2.4 я проверял на свеже-восстановленной из дампа базе, после VACUUM FULL ANALYZE в которой лишних версий записей и пустых страниц нема - отсюда разница.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34765618
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_v13или много данных не влезающих в памятьПамять тут ни при чем. Ни для SecScan, ни для IndexScan она не нужна.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34765675
Andrey Daeron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LeXa NalBat Andrey Daeronну и в чем разницо?OFFTOPIC

cost=4.85..4.86

cost=10.50..10.51

8.2.4 в два раза медленнее :-)
вот-вот!!!!
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34765701
alex_v13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LeXa NalBat alex_v13или много данных не влезающих в памятьПамять тут ни при чем. Ни для SecScan, ни для IndexScan она не нужна.

Тогда в shared_buffers оставим как есть по умолчанию, не помню сколько - 1000?

Выбор плана завист не только от предполагаемой ПГ ситуации с данным в таблице, но и от доступных ресурсов, чему я был свидетелем неоднократно.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34765781
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_v13Тогда в shared_buffers оставим как есть по умолчанию, не помню сколько - 1000?Возможно, для некоторой, при этом большой и серьезной, задачи большой shared_buffers не нужен.

alex_v13Выбор плана завист не только от предполагаемой ПГ ситуации с данным в таблице, но и от доступных ресурсов, чему я был свидетелем неоднократно.Насколько я понял из доки, выбор плана зависит исключительно от статистики по таблицам и параметров описанных в главе 17.6. доки.

На тест, иллюстрирующий вляние параметра shared_buffers (или других) на план запроса, хотелось бы взглянуть.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34765822
alex_v13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Например, вот цитата из доки:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
effective_cache_size (floating point)

Sets the planner’s assumption about the effective size of the disk cache that is available to a single
index scan. This is factored into estimates of the cost of using an index; a higher value makes it
more likely index scans will be used, a lower value makes it more likely sequential scans will
be used. When setting this parameter you should consider both PostgreSQL’s shared buffers and
the portion of the kernel’s disk cache that will be used for PostgreSQL data files. Also, take into
account the expected number of concurrent queries using different indexes, since they will have
to share the available space. This parameter has no effect on the size of shared memory allocated
by PostgreSQL, nor does it reserve kernel disk cache; it is used only for estimation purposes.
The value is measured in disk pages, which are normally  8192  bytes each. The default is  1000 .

авторa higher value makes it
more likely index scans will be used, a lower value makes it more likely sequential scans will
be used.

Это я так понимаю ключевое место всей фразы.
...
Рейтинг: 0 / 0
select count(*) from t - как быстрее получить прибл.к-во
    #34766039
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Effective_cache_size является параметром оптимизатора и не влияет больше ни на что, он описан в главе 17.6.
...
Рейтинг: 0 / 0
38 сообщений из 38, показаны все 2 страниц
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / select count(*) from t - как быстрее получить прибл.к-во
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]