powered by simpleCommunicator - 2.0.40     © 2025 Programmizd 02
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
92 сообщений из 92, показаны все 4 страниц
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078020
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго вечера,подскажите пожалуйста как сделать запрос
типо такого

Код: plsql
1.
select distinct p.* from person p  join person_channel pc on p.id = pc.person_id where  pc.channel_type =all of this-> ('SMS' ,'PUSH');



Нужно чтобы в результирующем наборе были только те записи,чей channel_type удовлетворяет строго всем типам из входящих аргументов,а не одному из
как было бы в случае с таким запросом
Код: plsql
1.
select distinct p.* from person p  join person_channel pc on p.id = pc.person_id where  pc.channel_type  in ('SMS' ,'PUSH')
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078121
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asv79
Доброго вечера,подскажите пожалуйста как сделать запрос
типо такого

Код: plsql
1.
select distinct p.* from person p  join person_channel pc on p.id = pc.person_id where  pc.channel_type =all of this-> ('SMS' ,'PUSH');



Нужно чтобы в результирующем наборе были только те записи,чей channel_type удовлетворяет строго всем типам из входящих аргументов,а не одному из
как было бы в случае с таким запросом
Код: plsql
1.
select distinct p.* from person p  join person_channel pc on p.id = pc.person_id where  pc.channel_type  in ('SMS' ,'PUSH')



из вашего не очень понятного описания я бы предположил такой вариант

Код: sql
1.
2.
3.
4.
5.
select p.* from person p 
where 
exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type='SMS')
and
exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type='PUSH');




--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078167
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,
такой вариант не подойдет,так как на вход в фильтр подается список значений
тоесть в результирующем наборе должны быть только те записи,которые имеют все перечисленные в списке типы и заранее никто не знает количество элементов в этом списке ,только тип - строка.

Код: plsql
1.
select distinct p.* from person p  join person_channel pc on p.id = pc.person_id where  pc.channel_type = have all of these elements (:list );
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078170
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asv79
на вход в фильтр подается список значений
как выглядит этот список ?
Это строка типа
Код: sql
1.
'''SMS'' ,''PUSH'''

?
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078172
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court
asv79
на вход в фильтр подается список значений
как выглядит этот список ?
Это строка типа
Код: sql
1.
'''SMS'' ,''PUSH'''

?

нет,это набор строковых значений- передается из java в формате List<String>
тоесть будет
Код: plsql
1.
'SMS','PUSH','EMAIL'.....,etc
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078174
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сейчас я изобразил вот такой вариант
Код: plsql
1.
2.
3.
select  p.* from respondent p  join respondent_channel rc on p.id = rc.respondent_id where  rc.channel_type = any(string_to_array(:some_list,','))
group by p.id
having count(distinct rc.channel_type )=array_length(string_to_array(:some_list,','),1);



где на вход будет подаваться 'SMS,PUSH,EMAIL,....etc' в виде строки

но мне это не очень подходит изза постфильтра - записей достаточно много и тащить их все из бд,затем накладывать having не очень хорошая идея ну и конечно не хочется преобразоывать список в строку типа 'SMS,PUSH,EMAIL,....etc' - проблем с этим нет,но это тоже не очень привествуется
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078177
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asv79
Maxim Boguk,
такой вариант не подойдет,так как на вход в фильтр подается список значений
тоесть в результирующем наборе должны быть только те записи,которые имеют все перечисленные в списке типы и заранее никто не знает количество элементов в этом списке ,только тип - строка.

Код: plsql
1.
select distinct p.* from person p  join person_channel pc on p.id = pc.person_id where  pc.channel_type = have all of these elements (:list );



Какие то проблемы сгенерировать нужное количество EXISTS в запросе?
Основной вопрос - вам вообще на производительность запроса наплевать?

Если на скорость работы наплевать то вариантов много можно придумать конечно.
Если нет то вариант с N exits будет скорее всего самым быстрым.

Ну и вопрос вам вообще что хочется - минимальный обьем програмирования или максимальная производительность в целом?


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078178
Alexander A. Sak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вариант с exists выглядит очень даже.
Просто в джава-коде надо пришедший список с channel_type не передавать в запрос как есть, а для каждого элемента делать and exists в запросе.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078181
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk
asv79
Maxim Boguk,
такой вариант не подойдет,так как на вход в фильтр подается список значений
тоесть в результирующем наборе должны быть только те записи,которые имеют все перечисленные в списке типы и заранее никто не знает количество элементов в этом списке ,только тип - строка.

Код: plsql
1.
select distinct p.* from person p  join person_channel pc on p.id = pc.person_id where  pc.channel_type = have all of these elements (:list );



Какие то проблемы сгенерировать нужное количество EXISTS в запросе?
Основной вопрос - вам вообще на производительность запроса наплевать?

Если на скорость работы наплевать то вариантов много можно придумать конечно.
Если нет то вариант с N exits будет скорее всего самым быстрым.

Ну и вопрос вам вообще что хочется - минимальный обьем програмирования или максимальная производительность в целом?


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru

производительность на первом месте ,подскажите пожалуйста как это будет выглядеть с генерацией EXISTS при условии что будет подаваться на вход List<String> либо вы предлагаете сделать это в джава коде?в джава коде проблем вроде быть не должно с этим спасибо за идею
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078184
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Предполагаю, что channel_type буквально десяток в прыжке разных. Если есть уникальный индекс person_channel (person_id, channel_type) то можно сделать

Код: sql
1.
2.
3.
select p.* from person p 
where 
exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type in ('SMS' ,'PUSH') limit 1 offset 1)


offset по числу значений в списке -1
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078199
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Melkij
Предполагаю, что channel_type буквально десяток в прыжке разных. Если есть уникальный индекс person_channel (person_id, channel_type) то можно сделать

Код: sql
1.
2.
3.
select p.* from person p 
where 
exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type in ('SMS' ,'PUSH') limit 1 offset 1)


offset по числу значений в списке -1

супер работает все отлично
а можно обьяснить принцип по которому данный запрос отрабатывает - я смотрю на него и не очень врубаюсь-тоесть сначала он находит те записи в которых есть хотя бы одно значение из списка ,потом смотрит число вхождений по офсету и выдает совпадение наверх?
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078205
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Melkij
Предполагаю, что channel_type буквально десяток в прыжке разных. Если есть уникальный индекс person_channel (person_id, channel_type) то можно сделать

Код: sql
1.
2.
3.
select p.* from person p 
where 
exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type in ('SMS' ,'PUSH') limit 1 offset 1)


offset по числу значений в списке -1

а что по производительности? если в таблице будет миллион персон это будет 1 млн подзапросов?
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078220
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Melkij
Предполагаю, что channel_type буквально десяток в прыжке разных. Если есть уникальный индекс person_channel (person_id, channel_type) то можно сделать

Код: sql
1.
2.
3.
select p.* from person p 
where 
exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type in ('SMS' ,'PUSH') limit 1 offset 1)


offset по числу значений в списке -1

по аналитике не очень этот запрос даже на 800 персонах и всего 10 каналах 2 мс время выполнения
правда planning time 0.277

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Seq Scan on respondent p  (cost=0.00..1870.24 rows=402 width=209) (actual time=0.186..2.018 rows=2 loops=1)
  Filter: (SubPlan 1)
  Rows Removed by Filter: 802
  SubPlan 1
    ->  Limit  (cost=1.15..2.30 rows=1 width=0) (actual time=0.002..0.002 rows=0 loops=804)
          ->  Seq Scan on respondent_channel rc  (cost=0.00..1.15 rows=1 width=0) (actual time=0.002..0.002 rows=0 loops=804)
"                Filter: ((channel_type = ANY ('{PUSH,SMS}'::text[])) AND (p.id = respondent_id))"
                Rows Removed by Filter: 10
Planning Time: 0.277 ms
Execution Time: 2.089 ms
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078263
PetroNotC Sharp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asv79,
В ветке по бд все равно что там у вас в java.
Вам надо либо сгенерить строку в in.
Либо передать таблицу list в хранимку
Либо сгенерить временную таблу в сессии бд и заджойнить ее с основной.
Смотрите по нагрузочному тесту.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078286
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asv79
а можно обьяснить принцип по которому данный запрос отрабатывает - я смотрю на него и не очень врубаюсь-тоесть сначала он находит те записи в которых есть хотя бы одно значение из списка ,потом смотрит число вхождений по офсету и выдает совпадение наверх?

при наличии уникального индекса при условии in (N элементов) после offset N-1 может остаться строка только в том случае, если каждый из N элементов присутствует в выборке. Если хоть даже одно нет - то offset всё проглотит, 0 строк в подзапросе, получим exists() = false

asv79
по аналитике не очень этот запрос даже на 800 персонах и всего 10 каналах 2 мс время выполнения

Добавьте данных. Ну миллионов 10 строк хотя бы.
На таких "объёмах" не имеет смысла ничего смотреть. Если же вам важны именно доли мс и 2мс уже медленно - то клиент-серверные субд вам вовсе не подходят. Латентность сети уже больше времени выполнения самих запросов получается.

asv79
если в таблице будет миллион персон это будет 1 млн подзапросов?

А зачем вам может понадобиться считать быстро весь миллион персон?
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078290
PetroNotC Sharp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Melkij,
+1 абстрактное время ни о чем не говорит. Да еще без реального набора данных по ТЗ.
Самой проблемы пока не видно.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078295
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PetroNotC Sharp,
на надо ничего там никуда джоинить и тд

Код: plsql
1.
2.
3.
select  p.* from respondent p where
  exists(select from respondent_channel rc where p.id = rc.respondent_id and   rc.channel_type ='SMS') and
  exists(select from respondent_channel rc where p.id = rc.respondent_id and   rc.channel_type ='PUSH')


динамически буду строить такой запрос в зависимости от количества элементов в ходящем списке и получаю

вот такие показатели и что не маловажно в других запросах идет seq сканироание ,в этом же примере оно идесное

собственно время меня удовлетворяет и я выберу этот вариант

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Nested Loop Semi Join  (cost=1.54..9.65 rows=1 width=209) (actual time=0.101..0.115 rows=2 loops=1)
  ->  Nested Loop  (cost=1.40..9.45 rows=1 width=217) (actual time=0.067..0.076 rows=2 loops=1)
        ->  HashAggregate  (cost=1.13..1.14 rows=1 width=8) (actual time=0.030..0.032 rows=2 loops=1)
              Group Key: rc.respondent_id
              Batches: 1  Memory Usage: 24kB
              ->  Seq Scan on respondent_channel rc  (cost=0.00..1.12 rows=1 width=8) (actual time=0.021..0.022 rows=2 loops=1)
                    Filter: (channel_type = 'SMS'::text)
                    Rows Removed by Filter: 8
        ->  Index Scan using respondent_pkey on respondent p  (cost=0.28..8.29 rows=1 width=209) (actual time=0.019..0.019 rows=1 loops=2)
              Index Cond: (id = rc.respondent_id)
  ->  Index Only Scan using respondent_id_channel on respondent_channel rc_1  (cost=0.14..0.17 rows=1 width=8) (actual time=0.017..0.017 rows=1 loops=2)
        Index Cond: ((respondent_id = p.id) AND (channel_type = 'PUSH'::text))
        Heap Fetches: 2
Planning Time: 0.389 ms
Execution Time: 0.241 ms
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078300
PetroNotC Sharp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asv79,
>на надо ничего там никуда джоинить и тд
= странный вы.
Вам дали 4 варианта решения.
Джойнить был 4ый.
Вы ВЗЯЛИ ПЕРВЫЙ и сказали "не надо ничего там...
))))) LOL
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078301
PetroNotC Sharp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asv79,
>собственно время меня удовлетворяет и я выберу этот вариант
= выше вам написали, что записей надо поболее. Но вам виднее.
Проблем нет.
Удачи!
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078306
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Melkij


asv79
если в таблице будет миллион персон это будет 1 млн подзапросов?

А зачем вам может понадобиться считать быстро весь миллион персон?

не понял вопроса? есть миллион записей в таблице и вот мне подсказали ,что запрос ,который вы посоветовали будет делать столько же подзапросов,сколько в таблице записей

речь вот про этот ваш запрос
Код: java
1.
2.
select  p.* from respondent p where
 exists(select from respondent_channel rc where p.id = rc.respondent_id and   rc.channel_type in (:some_list) limit 1 offset 2)
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078307
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PetroNotC Sharp
asv79,
>собственно время меня удовлетворяет и я выберу этот вариант
= выше вам написали, что записей надо поболее. Но вам виднее.
Проблем нет.
Удачи!

Так я из того что вы написали вообще ничего не понял
вот это например ->надо либо сгенерить строку в in
Я понял что вы хотите чтобы я из списка сделал строку типо 'SMS,EMAIL....etc'
это не проблема ,а где запрос сам куда это подставить?
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078324
PetroNotC Sharp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asv79,
Дак зачем если ничего не понял отвечать словом НЕТ?
))))
Первый пункт это динамический sql
Склеиваешь любой запрос.
Или в in условие
Или
Куски подзапросов
Код: sql
1.
2.
3.
select  p.* from respondent p where
  exists(select from respondent_channel rc where p.id = rc.respondent_id and   rc.channel_type ='SMS') and
  exists(select from respondent_channel rc where p.id = rc.respondent_id and   rc.channel_type ='PUSH')


И так далее.
Можно и вьюху генерить на событие вставки записи.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078325
PetroNotC Sharp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asv79,
Пятый вариант триггер поставить и перечень SMS,EMAIL....etc' будет всегда автоматом в табле person
Смотря что по бизнесу надо. OLAP/OLTP
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078901
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так еще можно попробовать.

Код: sql
1.
2.
3.
4.
5.
create materialized view sms_push_respondents 
as
select  p.* from respondent p where
  exists(select from respondent_channel rc where p.id = rc.respondent_id and   rc.channel_type ='SMS') and
  exists(select from respondent_channel rc where p.id = rc.respondent_id and   rc.channel_type ='PUSH');
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078908
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk

... вариант с N exits будет скорее всего самым быстрым.


это сомнительное утверждение для произвольного N
До какого-то порога (допустим, N ~ 7-8) так и будет.
Потом я бы ожидал перехода первенства к какому-то другому варианту.
Но не факт, что оказавшийся следующим победителем, сохранит лидерство для "слишком больших" N и person_channel

Код: sql
1.
2.
3.
4.
5.
select p.* from person p 
where 
exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type='SMS')
and
exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type='PUSH');



здесь exists может либо использоваться в качестве фильтра, либо преобразуется в join
В первом случае быстрее начнут "отдаваться строки", во втором, по вероятности, запрос в целом отработает быстрее,
при наличии подходящих индексов.

Смотрите, функционально этот запрос эквивалентен такому:
(а при трансформации в джойн как-то так и будет, с точностью до перестановки порядка таблиц)
Код: sql
1.
2.
3.
4.
5.
6.
select p.* from person p 
where 
exists (select from person_channel pc1, person_channel pc2 
          where p.id = pc1.person_id and pc1.channel_type='SMS'
            and  pc2.person_id =pc1.person_id and pc2.channel_type='PUSH'
)


тогда при добавлении третьего элемента поиска получается вот что:
Код: sql
1.
2.
3.
4.
5.
6.
7.
select p.* from person p 
where 
exists (select from person_channel pc1, person_channel pc2, person_channel pc3 
          where p.id = pc1.person_id and pc1.channel_type='SMS'
            and  pc2.person_id =pc1.person_id and pc2.channel_type='PUSH'
            and  pc3.person_id =pc2.person_id and pc3.channel_type='EMAIL'
)


Даже при наличии индексов, деградация производительности такого соединения по мере роста списка поиска,
растёт достаточно быстро, чтобы проиграть, в конце концов, какому-то из альтернативных вариантов.
Скорее всего, построенному на группировке тем или иным способом....
имхо...

PS (типа, в коллекцию)
среди вариантов записи реляционного деления встречается и вариант, который в данном случае мог бы быть выписан в таком роде:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
select p.* from person p 
where 
p.id not in (
      select person_id 
      from (
        select p.id as person_id, channel_type 
        from person p, unnest(array['SMS', 'PUSH', 'EMAIL']) channel(channel_type)
        except 
        select pc.person_id, pc.channel_type  
        from person_channel pc 
      )
    )


визуально он не похож на многообещающий в плане производительности.
Хотя, на средних размерах данных и средней длине списка, может оказаться не сильно и хуже прочих.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078941
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby,

Производительность в варианте с multiple exists перво на перво будет зависеть от селективности САМОГО селективного фильтра в наборе.
Т.е. если условно у вас в условии на channel_type 'SMS' ,'PUSH', 'доставка голубями'
и с 'SMS' ,'PUSH' по 10 миллионов строк а с 'доставка голубями' всего 10 строк
то вариант с exists выйграет у любого мыслимого альтернативного варианта
просто потому что он начнет с semijoin от
exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type= 'доставка голубями' )
и далее быстро проверит найденные 10 строк по остальным 2м exits.

Все остальные варианты будут так или иначе скатываться с полным переборам таблицы person
а зачастую и таблицы person_channel с соответствующей печальной производителностью.

Если же у вас там 10 низкоселективных channel_type в условии - там надо думать как лучше и сравнивать на конкретных реальных или синтетических данных.


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078947
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,

Не думаю.

То, что вы описываете, видится как комбинация джойна с фильтром, при которой какие-то exists уедут в семиджойн, а какие-то останутся в фильтрах.
Допустим, что целевой построитель плана выполнения запроса достаточно умен, чтобы именно так и работать на релевантной статистике.
Тогда та часть, которая останется в фильтрах отработает за разумное время только при наличии структур типа bitmap-индексов.
(И, если они есть, то есть смысл вообще все оставить в фильтре)
Иначе кролик сдохнет под тяжестью множественных лукапов.

Принципиальный момент в такого рода задаче - по постановке всяко требуется полный просмотр person_channel,
то есть фильтрация не снижает совсем, или не снижает сильно объём просматриваемых данных, даже при пробеге по bitmap-индексу.
В этих обстоятельствах безфильтровый полный пробег по person_channel с группировкой и агрегацией вполне смотрится.
И тем лучше, чем больше сама person_channel и список обязательных требований.
Мне кажется вполне разумным ожидать, что рано или поздно он опередит вариант с exists.
А при отсутствии bitmap-индексов - опередит несомненно, и на достаточно малых значениях длинах списка требований (пусть будет - ~7-8 ).

Другой вопрос, что в варианте с группировкой кажется предпочтительным вместо ( Count(*) from таблица_требований )
иметь групповую функцию, дающую слепок группы требований, с которым непосредственно можно было бы
сравнивать слепок списка каналов конкретного person_id.
Для нумерованных списков длиной <= 64 можно было использовать bit_and, благо, он есть в postgress.
Преимущество Count в том, что он сработает стандартно на любых объёмах, без изобретения дополнительных конструкций
для поддержки списков требований большего размера.

PS
Думаю, что в случае использования технологий того рода, что в oracle называют "exadata" -
с фильтрацией на диске, блочными индексами и прочими чудесами, даже bitmap-индексам
не стоит начинать соревноваться с простым и незатейливым полным просмотром.
имхо.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078950
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby,
в паралельной теме мне предложили создать функциию ,которая будет создавать в памяти сессии временную таблицу с типами каналов

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
create function getRespondtenByTypes(VARIADIC mas text[]) returns setof respondent as
$$
declare str text;
  begin
  create temp table tmp_types(
  type text);
  foreach str in array mas
  loop
  insert into tmp_types (type) values (str);
end loop ;
return query select distinct  p.* from respondent p join respondent_channel rc on p.id = rc.respondent_id join tmp_types tt on rc.channel_type=tt.type
  
end;
  $$
language plpgsql;


Надо логику запроса поправить ,учитывая наличие временной таблицы,если конечно такой вариант вообще имеет место быть
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078951
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
с временной таблицей вы можете использовать любую из работоспособных ранее показанных логик в обоих ветка.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078952
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby
с временной таблицей вы можете использовать любую из работоспособных ранее показанных логик в обоих ветка.

а какой запрос в таком случае будет работать с временной таблицей- я честно не достаточно силен в такого рода запросах
если не сложно покажите рабочий пример .
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078955
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby,

"Принципиальный момент в такого рода задаче - по постановке всяко требуется полный просмотр person_channel," - с чего вы это взяли?
Задача решения с exists именно избежать полного просмотра.


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078957
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby,

Для закрытия вопроса - вот полный test case про то как оно в реальности работает

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
--создаем 1.000.000 persons
mboguk=# create database test;
CREATE DATABASE

mboguk=# \c test
You are now connected to database "test" as user "mboguk".

test=# create table person as select id from generate_series(1,1000000) as g(id);
SELECT 1000000

test=# alter table person add primary key (id);
ALTER TABLE

test=# vacuum freeze analyze person;
VACUUM


--создаем person_channel с типами SMS, PUSH, POSTAL DOVE c распределением вида 1:1:0.001
test=# create table person_channel as select person_id, case when random()>0.5 then 'SMS' when random()<0.001 then 'POSTAL DOVE' else 'PUSH' end as channel_type from generate_series(1,1000000) as g(person_id);
SELECT 1000000

test=# insert into person_channel select pc1.* FROM (select person_id, case when random()>0.5 then 'SMS' when random()<0.001 then 'POSTAL DOVE' else 'PUSH' end as channel_type from generate_series(1,1000000) as g(person_id)) as pc1 where not exists (select from person_channel pc2 where pc2.person_id=pc1.person_id and pc2.channel_type=pc1.channel_type);
INSERT 0 500390

test=# create UNIQUE index person_channel_person_id_channel_type on person_channel(person_id, channel_type);
CREATE INDEX

test=# create index person_channel_channel_type on person_channel(channel_type);
CREATE INDEX

test=# vacuum freeze ANALYZE person_channel;
VACUUM

test=# select count(*), channel_type from person_channel group by 2;
 count  | channel_type 
--------+--------------
   1034 | POSTAL DOVE
 749497 | PUSH
 749859 | SMS



А теперь тест:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
test=# explain analyze select * from person p where
exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type='SMS')
and exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type='PUSH')
and exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type='POSTAL DOVE')
;
                                                                                  QUERY PLAN                                                                                   
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop  (cost=13.85..7725.00 rows=590 width=4) (actual time=25.854..25.856 rows=0 loops=1)
   ->  Nested Loop  (cost=13.42..7358.65 rows=784 width=12) (actual time=0.829..22.298 rows=510 loops=1)
         ->  Nested Loop  (cost=12.99..6868.01 rows=1050 width=8) (actual time=0.811..12.571 rows=1034 loops=1)
               ->  Bitmap Heap Scan on person_channel pc_2  (cost=12.56..2875.39 rows=1050 width=4) (actual time=0.787..3.930 rows=1034 loops=1)
                     Recheck Cond: (channel_type = 'POSTAL DOVE'::text)
                     Heap Blocks: exact=953
                     ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..12.30 rows=1050 width=0) (actual time=0.398..0.398 rows=1034 loops=1)
                           Index Cond: (channel_type = 'POSTAL DOVE'::text)
               ->  Index Only Scan using person_pkey on person p  (cost=0.42..3.80 rows=1 width=4) (actual time=0.007..0.007 rows=1 loops=1034)
                     Index Cond: (id = pc_2.person_id)
                     Heap Fetches: 0
         ->  Index Only Scan using person_channel_person_id_channel_type on person_channel pc_1  (cost=0.43..0.47 rows=1 width=4) (actual time=0.008..0.008 rows=0 loops=1034)
               Index Cond: ((person_id = p.id) AND (channel_type = 'PUSH'::text))
               Heap Fetches: 0
   ->  Index Only Scan using person_channel_person_id_channel_type on person_channel pc  (cost=0.43..0.47 rows=1 width=4) (actual time=0.006..0.006 rows=0 loops=510)
         Index Cond: ((person_id = p.id) AND (channel_type = 'SMS'::text))
         Heap Fetches: 0
 Planning Time: 3.106 ms
 Execution Time: 25.939 ms



И никаких полных переборов person_channel как и ожидалось.
"Допустим, что целевой построитель плана выполнения запроса достаточно умен, чтобы именно так и работать на релевантной статистике." - таки это базовая его функциональность - решать как такие вещи лучше делать.

Учите матчасть и проверяйте свои теории на тестовых данных перед тем как советовать.


PS: и даже в случае отсутствия селективного фильтра в наборе - продолжает работать неплохо и без
seq scan по person_channel
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
explain analyze select * from person p where 
exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type='SMS')
and exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type='PUSH')
--and exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type='POSTAL DOVE')
;
                                                                             QUERY PLAN                                                                              
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Hash Join  (cost=74774.24..113292.60 rows=561997 width=4) (actual time=417.767..1089.731 rows=499356 loops=1)
   Hash Cond: (p.id = pc.person_id)
   ->  Hash Join  (cost=37273.93..65055.94 rows=746794 width=8) (actual time=188.063..608.533 rows=749497 loops=1)
         Hash Cond: (p.id = pc_1.person_id)
         ->  Seq Scan on person p  (cost=0.00..14425.00 rows=1000000 width=4) (actual time=0.019..61.047 rows=1000000 loops=1)
         ->  Hash  (cost=25021.01..25021.01 rows=746794 width=4) (actual time=187.852..187.853 rows=749497 loops=1)
               Buckets: 131072  Batches: 16  Memory Usage: 2676kB
               ->  Bitmap Heap Scan on person_channel pc_1  (cost=8324.08..25021.01 rows=746794 width=4) (actual time=17.158..98.042 rows=749497 loops=1)
                     Recheck Cond: (channel_type = 'PUSH'::text)
                     Heap Blocks: exact=7362
                     ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..8137.38 rows=746794 width=0) (actual time=16.289..16.290 rows=749497 loops=1)
                           Index Cond: (channel_type = 'PUSH'::text)
   ->  Hash  (cost=25153.48..25153.48 rows=752546 width=4) (actual time=229.523..229.524 rows=749859 loops=1)
         Buckets: 131072  Batches: 16  Memory Usage: 2677kB
         ->  Bitmap Heap Scan on person_channel pc  (cost=8384.66..25153.48 rows=752546 width=4) (actual time=47.556..133.339 rows=749859 loops=1)
               Recheck Cond: (channel_type = 'SMS'::text)
               Heap Blocks: exact=7362
               ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..8196.52 rows=752546 width=0) (actual time=36.843..36.844 rows=749859 loops=1)
                     Index Cond: (channel_type = 'SMS'::text)
 Planning Time: 1.277 ms
 JIT:
   Functions: 22
   Options: Inlining false, Optimization false, Expressions true, Deforming true
   Timing: Generation 4.455 ms, Inlining 0.000 ms, Optimization 0.370 ms, Emission 9.141 ms, Total 13.967 ms
 Execution Time: 1106.620 ms
(25 rows)
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078960
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,

Не подскажите а как будет выглядеть вариант запроса ,если я запишу типы каналов в временную таблицу ?заранее спасибо
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078961
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asv79,

Я бы не стал... временные таблицы в PG очень дорогое удовольствие и на вашей задаче они выйгрыша не дадут вообще ни в каком варианте (тем более если запрос предполагается вызывать часто).
Советы про временные таблицы обычно идут от старых оракловодов где это могло помогать временами.

Сам факт что появляется слово distinct - уже убивает любую надежду на разумную производительность.

Тогда уж вместо временной таблицы конструктор values или unnest использовать (но выйгрыша это не даст).

PS: в 99% случаев подобных задач если в вашем решении появилось слово distinct - вы что то сильно не то делаете.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078963
Фотография asv79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,

Спасибо .Применил ваш вариант первоначальный
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078964
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,

Признаю, это не было умной идеей - свой пост мне оформлять в виде обращения к вам.
Хотя я мог бы догадаться об этом по стилю вашей подписи.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40078973
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PetroNotC Sharp
asv79,
Пятый вариант триггер поставить и перечень SMS,EMAIL....etc' будет всегда автоматом в табле person
Смотря что по бизнесу надо. OLAP/OLTP

Хороший вариант. Но я-бы обсудил различные сценарии обратных (компенсирующих) DML
когда мы например удаляем "SMS" из дочерней таблицы. И возможную легкую денормализацию
родительской таблички.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079002
PetroNotC Sharp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,
Конечно. Делал такое и была функция генерируйВьюху()
А она вызывалась по триггеру на события как вставки так и удаления.
То есть мы меняли схему бд.
Но можно менять и нормализацию.
Мы генерим идеи, а выбирает архитектор по многим факторам.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079004
PetroNotC Sharp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,
+1 про distinct
Не люблю его)
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079009
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PetroNotC Sharp
mayton,
Конечно. Делал такое и была функция генерируйВьюху()
А она вызывалась по триггеру на события как вставки так и удаления.
То есть мы меняли схему бд.
Но можно менять и нормализацию.
Мы генерим идеи, а выбирает архитектор по многим факторам.

Я вот щас еще раз сравнил реализацию materialized views в Оракле и в PG.
В последнем - тухляк. Не поддерживаются fast-режимы. Это когда мы обновляем
не весь mview а отслеживаем только изменённые data-rows по журналам.

Всему импортозамещению я сочувствую. PG - конешно опенсорсный. Но блин... это-же
сколько тонн человеко-часов надо потратить чтобы взять PG и впилить в него фичу
(реально классную фичу) из Оракла. Мне-бы до конца жизни хватило сидеть и разбираться
в исходниках постгреса. Увлекательное занятие было-бы на пенсии. Мдя.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079028
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PetroNotC Sharp
Maxim Boguk,
+1 про distinct
Не люблю его)

В тех специальных условиях, которые для себя сформулировал Максим, путём определения уникального индекса, никакого distinct технически не требуется.
В данном конкретном случае существо дела совершенно в другом.

2mayton
содержательный oracle-проект не только на db2, но даже на tibero db весьма непросто перенести.
А перенести в postgress, для проекта сложностью в три - пять сотен человеко-лет,
это примерно как человечеству переселиться, если не в соседнюю галактику, то, как минимум, на спутники Сатурна или Юпитера.
При том, что круг идей и совокупность алгоритмов у любых разумно построенных субд совпадает на 95-98%
Оставшиеся пара-тройка процентов образуют непреодолимую пропасть.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079036
PetroNotC Sharp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Господа.
Правильно я понял что сабж относится к области:
- вхождение множества А в множество Б.
Или термин выше относится к варианту с временной таблицей?
Например такой вариант составил
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
with

   t2 as (select * from (values ('POST'), ('GET')) as p (typ))

 

select p.id,

CASE

 WHEN 

 ( exists

               (

                    (select typ from t2)

                     EXCEPT

                    (select pc.type from person_channel pc where pc.person_id = p.id)

                )

) THEN 'NO'

ELSE 'YES'

END

from person p
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079041
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PetroNotC Sharp
Господа.
Правильно я понял что сабж относится к области:
- вхождение множества А в множество Б.

ммм. не то, чтобы совсем не так, но, в целом - нет.

Пусть Б- обязательное множество экзаменов, при сдаче которых студент из А-множетсва результатов сдачи экзаменов, переводится на следующий курс.
(Здесь предполагается, что "двойки" в A не пишутся - если двойка, у студента просто нет записи в результатах экзаменов А)
варианты задачи:

1) Требуется отобрать для перевода на следующий курс всех таких студентов, которые сдали не менее, чем множество обязательных экзаменов (требований). Если кроме обязательных сдали какие-то еще - то такие годятся, их тоже, несомненно переведут на следующий курс.
Это обычное реляционное деление А на Б, с допустимым "остатком"

2) Отыскиваются только те, кто сдал набор экзаменов, точно равный указанному с множестве Б - не меньше, но и не больше.
Это называют точным реляционным делением.
Например, это претенденты на обычную стипендию. В них нехорошо помещать тех, кто сдал экзаменов больше обязательного списка.
Таких надо в претенденты на повышенную стипендию определять.

То есть это задача на отбор персон, соответствующих квалификационным требованиям.
Если сказано в наборе обязательных требований к квалификации кандидата
автор Java 11, Kotlin, Spring Boot, WebFlux, R2DBC и прочее;
• legacy: Java 8, Groovy, Spring, Hibernate, ActiveMQ;
• Git, Gitlab, Gitlab-CI;
• Docker и Kubernetes;
• JIRA, Confluence, Agile Scrum;
• Quality gate: code coverage + vulnerabilities + maintainability.

И хотя бы одного слова в резюме не встречается (например - "прочее"), то кандидат в любом случае на собеседование не вызывается.
А если есть лишние слова - Fortran, Ada, C++, Julia, Oracle, Postgress, MySql,
то человек вызывается на собеседование, если "остаток от деления" допускается, и не вызывается, если выполняется точное деление, "без остатка".
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079050
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby,

Уникальный индекс в моём решении не требуется и никак на его эффект и скорость работы не влияет.

PS: в контексте задачи обычно если мы о реляционном делении говорим обычно студент не может иметь два одинаковых сданных экзамена поэтому uniq обычно предполагается.


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
test=# drop table person_channel;
DROP TABLE
test=# create table person_channel as select person_id, case when random()>0.5 then 'SMS' when random()<0.001 then 'POSTAL DOVE' else 'PUSH' end as channel_type from generate_series(1,1000000) as g(person_id);
SELECT 1000000
test=# insert into person_channel select pc1.* FROM (select person_id, case when random()>0.5 then 'SMS' when random()<0.001 then 'POSTAL DOVE' else 'PUSH' end as channel_type from generate_series(1,1000000) as g(person_id)) as pc1;
INSERT 0 1000000
test=# create index person_channel_person_id_channel_type on person_channel(person_id, channel_type);
CREATE INDEX

test=# create index person_channel_channel_type on person_channel(channel_type);
CREATE INDEX

test=# vacuum freeze ANALYZE person_channel;
VACUUM

--куча дубликатов
test=# select count(*), channel_type from person_channel group by 2;
 count  | channel_type 
--------+--------------
    953 | POSTAL DOVE
 999390 | PUSH
 999657 | SMS




Код: sql
1.
2.
3.
4.
5.
test=# explain analyze select * from person p where exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type='SMS')
and
exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type='PUSH')
and exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type='POSTAL DOVE')
;


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
                                                                                   QUERY PLAN                                                                                   
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop Semi Join  (cost=2700.45..7174.53 rows=865 width=4) (actual time=22.187..22.190 rows=0 loops=1)
   ->  Nested Loop Semi Join  (cost=2700.03..6747.99 rows=886 width=12) (actual time=3.007..19.106 rows=477 loops=1)
         ->  Nested Loop  (cost=2699.60..6309.92 rows=910 width=8) (actual time=2.983..10.912 rows=953 loops=1)
               ->  HashAggregate  (cost=2699.17..2708.50 rows=933 width=4) (actual time=2.950..3.506 rows=953 loops=1)
                     Group Key: pc_2.person_id
                     Batches: 1  Memory Usage: 129kB
                     ->  Index Scan using person_channel_channel_type on person_channel pc_2  (cost=0.43..2696.84 rows=933 width=4) (actual time=0.039..2.053 rows=953 loops=1)
                           Index Cond: (channel_type = 'POSTAL DOVE'::text)
               ->  Index Only Scan using person_pkey on person p  (cost=0.42..3.86 rows=1 width=4) (actual time=0.007..0.007 rows=1 loops=953)
                     Index Cond: (id = pc_2.person_id)
                     Heap Fetches: 0
         ->  Index Only Scan using person_channel_person_id_channel_type on person_channel pc  (cost=0.43..0.47 rows=1 width=4) (actual time=0.008..0.008 rows=1 loops=953)
               Index Cond: ((person_id = p.id) AND (channel_type = 'SMS'::text))
               Heap Fetches: 0
   ->  Index Only Scan using person_channel_person_id_channel_type on person_channel pc_1  (cost=0.43..0.47 rows=1 width=4) (actual time=0.006..0.006 rows=0 loops=477)
         Index Cond: ((person_id = p.id) AND (channel_type = 'PUSH'::text))
         Heap Fetches: 0
 Planning Time: 1.697 ms
 Execution Time: 22.298 ms
(19 rows)

Альтернативное решение которое действительно может быть быстрее если много низкоселективных условий будет иметь вид:

SELECT * from person p where p.id IN (SELECT person_id FROM person_channel WHERE channel_type IN ('SMS', 'PUSH', 'POSTAL DOVE') GROUP BY person_id HAVING count(distinct channel_type)>=3);

которое будет иметь константное более менее время работы вне зависимости от селективности набора channel_type
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
test=# explain analyze SELECT  * from person p where p.id IN (SELECT person_id FROM person_channel WHERE channel_type IN ('SMS',  'PUSH',  'POSTAL DOVE') GROUP BY person_id HAVING count(distinct channel_type)>=3);
                                                                                       QUERY PLAN                                                                                        
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Merge Join  (cost=0.85..120641.68 rows=341747 width=4) (actual time=1188.548..1188.550 rows=0 loops=1)
   Merge Cond: (p.id = person_channel.person_id)
   ->  Index Only Scan using person_pkey on person p  (cost=0.42..25980.42 rows=1000000 width=4) (actual time=0.105..0.106 rows=1 loops=1)
         Heap Fetches: 0
   ->  GroupAggregate  (cost=0.43..84471.95 rows=341747 width=4) (actual time=1177.114..1177.115 rows=0 loops=1)
         Group Key: person_channel.person_id
         Filter: (count(DISTINCT person_channel.channel_type) >= 3)
         Rows Removed by Filter: 1000000
         ->  Index Only Scan using person_channel_person_id_channel_type on person_channel  (cost=0.43..61656.43 rows=2000000 width=8) (actual time=0.088..304.581 rows=2000000 loops=1)
               Filter: (channel_type = ANY ('{SMS,PUSH,"POSTAL DOVE"}'::text[]))
               Heap Fetches: 0
 Planning Time: 0.474 ms
 JIT:
   Functions: 8
   Options: Inlining false, Optimization false, Expressions true, Deforming true
   Timing: Generation 3.186 ms, Inlining 0.000 ms, Optimization 0.577 ms, Emission 10.271 ms, Total 14.034 ms
 Execution Time: 1191.897 ms



Что проигрывает в 30 раз версии с exists НА СЕЛЕКТИВНОМ ФИЛЬТРЕ.

Если же фильтр не селективен то получаем сравнимое время работы:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
test=# explain analyze SELECT  * from person p where p.id IN (SELECT person_id FROM person_channel WHERE channel_type IN ('SMS',  'PUSH') GROUP BY person_id HAVING count(distinct channel_type)>=2);
                                                                                       QUERY PLAN                                                                                        
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Merge Join  (cost=0.85..118137.02 rows=341747 width=4) (actual time=10.267..1458.642 rows=500030 loops=1)
   Merge Cond: (p.id = person_channel.person_id)
   ->  Index Only Scan using person_pkey on person p  (cost=0.42..25980.42 rows=1000000 width=4) (actual time=0.058..91.289 rows=1000000 loops=1)
         Heap Fetches: 0
   ->  GroupAggregate  (cost=0.43..81967.29 rows=341747 width=4) (actual time=0.123..1241.724 rows=500030 loops=1)
         Group Key: person_channel.person_id
         Filter: (count(DISTINCT person_channel.channel_type) >= 2)
         Rows Removed by Filter: 499970
         ->  Index Only Scan using person_channel_person_id_channel_type on person_channel  (cost=0.43..59156.43 rows=1999067 width=8) (actual time=0.071..313.379 rows=1999047 loops=1)
               Filter: (channel_type = ANY ('{SMS,PUSH}'::text[]))
               Rows Removed by Filter: 953
               Heap Fetches: 0
 Planning Time: 0.402 ms
 JIT:
   Functions: 8
   Options: Inlining false, Optimization false, Expressions true, Deforming true
   Timing: Generation 2.104 ms, Inlining 0.000 ms, Optimization 0.373 ms, Emission 9.337 ms, Total 11.813 ms
 Execution Time: 1474.000 ms

vs

test=# explain analyze select * from person p where exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type='SMS')
and
exists (select from person_channel pc where p.id = pc.person_id and pc.channel_type='PUSH')
;                                                                                                     
                                                                                        QUERY PLAN                                                                                        
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Merge Semi Join  (cost=4.88..153455.42 rows=950476 width=4) (actual time=7.121..640.741 rows=500030 loops=1)
   Merge Cond: (p.id = pc_1.person_id)
   ->  Merge Semi Join  (cost=1.71..89851.05 rows=973689 width=8) (actual time=7.061..386.027 rows=750082 loops=1)
         Merge Cond: (p.id = pc.person_id)
         ->  Index Only Scan using person_pkey on person p  (cost=0.42..25980.42 rows=1000000 width=4) (actual time=0.055..85.834 rows=1000000 loops=1)
               Heap Fetches: 0
         ->  Index Only Scan using person_channel_person_id_channel_type on person_channel pc  (cost=0.43..49139.10 rows=998267 width=4) (actual time=0.098..116.771 rows=999657 loops=1)
               Index Cond: (channel_type = 'SMS'::text)
               Heap Fetches: 0
   ->  Index Only Scan using person_channel_person_id_channel_type on person_channel pc_1  (cost=0.43..49164.43 rows=1000800 width=4) (actual time=0.045..114.944 rows=999390 loops=1)
         Index Cond: (channel_type = 'PUSH'::text)
         Heap Fetches: 0
 Planning Time: 0.974 ms
 JIT:
   Functions: 8
   Options: Inlining false, Optimization false, Expressions true, Deforming true
   Timing: Generation 1.916 ms, Inlining 0.000 ms, Optimization 0.340 ms, Emission 6.218 ms, Total 8.474 ms
 Execution Time: 655.357 ms
(18 rows)



В итоге еще раз подтверждается правило что надо тестировать тестировать и еще раз тестировать разные варианты как минимум на синтетике а в идеале на копии реальных данных и главное реальных запросов и фильтров (понимая распределения этих фильтов в production).

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079051
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton
PetroNotC Sharp
mayton,
Конечно. Делал такое и была функция генерируйВьюху()
А она вызывалась по триггеру на события как вставки так и удаления.
То есть мы меняли схему бд.
Но можно менять и нормализацию.
Мы генерим идеи, а выбирает архитектор по многим факторам.

Я вот щас еще раз сравнил реализацию materialized views в Оракле и в PG.
В последнем - тухляк. Не поддерживаются fast-режимы. Это когда мы обновляем
не весь mview а отслеживаем только изменённые data-rows по журналам.

Всему импортозамещению я сочувствую. PG - конешно опенсорсный. Но блин... это-же
сколько тонн человеко-часов надо потратить чтобы взять PG и впилить в него фичу
(реально классную фичу) из Оракла. Мне-бы до конца жизни хватило сидеть и разбираться
в исходниках постгреса. Увлекательное занятие было-бы на пенсии. Мдя.


Практика показала что если мы переносим сколь угодно большой ВЕБ проект (а я переносил как минимум один из топовых сайтов рунета с mysql на postgres в одни руки) - это не так уж сложно и вполне поддается решению за разумное время.

Совсем другое дело когда надо перенести какой то биллинг или АБС с миллионами строк хранимок и (mat)views - там сложность переноса в том что там нарушена изоляция данных от кода и фактически мы не базу с данными и формализованным языком SQL переносим а переносим весь проект с языка А (хранимки ORACLE) на язык Б (хранимки postgresql) - и тут обьем работ конечно очень большой
(хотя учитывая цену лицензии на оракел часто оправданный... не всегда конечно).
Это как с С++ на Java переписать... вроде и похоже но автоматических трансляторов рабочих не существует.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079052
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Интересная эта штука.... partial indexes. Вот попробовал. Но нужны реальные вероятности и взаимовязи
предикатов SMS/Push/Email. На синтетике - не те ощущения. Вобщем пускай Стасик проверяет если хочет.
И триггер надо добавить.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
-- Denormalized respndents

drop table respondent;

create table respondent(
   person_id integer primary key,   
   channel_type_sms boolean,
   channel_type_push boolean,
   channel_type_email boolean
   -- all other respondent stuff...
);

-- TODO: Implement trigger for each row to update predicates
-- .......

-- Generate random noize with 0.25 probability of predicates


DO 
$code$
BEGIN
    FOR i IN 1..1000000 LOOP
      insert into respondent values(i, random() < 0.25, random() < 0.25, random() < 0.25);
    END LOOP;
    raise notice 'OK';
END
$code$;

--

analyze verbose respondent;
INFO:  analyzing "public.respondent"
INFO:  "respondent": scanned 4425 of 4425 pages, containing 1000000 live rows and 0 dead rows; 30000 rows in sample, 1000000 estimated total rows
ANALYZE


explain analyze select * from respondent where channel_type_sms and channel_type_push and channel_type_email;
-----------------------------------------------------------------------------------------------------------------------------
 Gather  (cost=1000.00..11175.17 rows=15835 width=7) (actual time=0.410..36.277 rows=15794 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   ->  Parallel Seq Scan on respondent  (cost=0.00..8591.67 rows=6598 width=7) (actual time=0.034..27.342 rows=5265 loops=3)
         Filter: (channel_type_sms AND channel_type_push AND channel_type_email)
         Rows Removed by Filter: 328069
 Planning Time: 0.225 ms
 Execution Time: 36.849 ms
(8 rows)


-- Partial index. TODO: Investigate for probability range (0.25 - 0.95) benefit.


CREATE INDEX respondent_function ON respondent(person_id) WHERE NOT (channel_type_sms AND channel_type_push AND channel_type_email);

dht=> explain analyze select * from respondent where channel_type_sms and channel_type_push and channel_type_email;

explain analyze select * from respondent where channel_type_sms and channel_type_push and channel_type_email;
-----------------------------------------------------------------------------------------------------------------------------
 Gather  (cost=1000.00..11164.17 rows=15725 width=7) (actual time=0.286..36.859 rows=15794 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   ->  Parallel Seq Scan on respondent  (cost=0.00..8591.67 rows=6552 width=7) (actual time=0.023..28.560 rows=5265 loops=3)
         Filter: (channel_type_sms AND channel_type_push AND channel_type_email)
         Rows Removed by Filter: 328069
 Planning Time: 0.311 ms
 Execution Time: 37.510 ms
(8 rows)
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079054
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk
booby,

Уникальный индекс в моём решении не требуется и никак на его эффект и скорость работы не влияет.
...


вот что вы говорили:
Maxim BogukСам факт что появляется слово distinct - уже убивает любую надежду на разумную производительность.
Так вот, неизбежно distinct появляется только в варианте запроса с группировкой с последующим фильтром
вида
Код: sql
1.
Having (Select count(*) From B) = Count(distinct A.subject)


когда пара (A.person_id, A.subject) неуникальна.
И, если такая пара ограничена уникальностью, то это единственное обязательное вхождение distinct автоматически исчезает.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079057
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
хм.
на миллионе записей:
Код: sql
1.
2.
3.
4.
5.
               ->  Bitmap Heap Scan on person_channel pc_2  (cost=12.56..2875.39 rows=1050 width=4) (actual time=0.787..3.930 rows=1034 loops=1)
                     Recheck Cond: (channel_type = 'POSTAL DOVE'::text)
                     Heap Blocks: exact=953
                     ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..12.30 rows=1050 width=0) (actual time=0.398..0.398 rows=1034 loops=1)
                           Index Cond: (channel_type = 'POSTAL DOVE'::text)



а на двух миллионах:
Код: sql
1.
2.
3.
4.
5.
               ->  HashAggregate  (cost=2699.17..2708.50 rows=933 width=4) (actual time=2.950..3.506 rows=953 loops=1)
                     Group Key: pc_2.person_id
                     Batches: 1  Memory Usage: 129kB
                     ->  Index Scan using person_channel_channel_type on person_channel pc_2  (cost=0.43..2696.84 rows=933 width=4) (actual time=0.039..2.053 rows=953 loops=1)
                           Index Cond: (channel_type = 'POSTAL DOVE'::text)



Как оперативка у бобика сдохла для построения битмап-карты, так сразу и Group By заиграл, негромкой дудочкой.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079062
PetroNotC Sharp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby,
Не, ну у нас то задача определена и вариант только один.
Множество детей у мастера А должно обязательно содержать множество Б называемых автором фильтры.
Поэтому и спросил как это одной фразой назвать.
Так как оператор in проверяет вхождение одного элемента.
А оператор EXCEPT то что надо но вроде только от постгри.
Решение выше вообще вроде работает.
Возможно это называется как вы написали
Это обычное реляционное деление А на Б, с допустимым "остатком".
ОК.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079078
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby,

Разница в том что в первом плане есть uniq индекс а во втором нет.
Поэтому в первом плане не требуется стадия убирания дубликатов строк.
Да и по скорости они не отличаются почти.

32MB work_mem достаточно на очень дофига bitmap scan строк.


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079706
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
добрался наконец до sqlfiddle - поиграться, и лучше понять, что происходит
Долгое время никак не мог получить планов, похожих на те, "за которые я воевал",
затем подумал - ну уж intersect-то должен...
И, бинго! - intersect как раз и показал ... ну почти то, что требуется.

В сравнении, стало более-менее понятно, как пытаться этого же примерно
добиваться и для group by и для join-вариантов - надо всего лишь лишить систему "удобного", с её точки зрения,
индекса для соединения и не давать возможности джойну зацепиться за высокоселективный параметр в фильтре.

Group by показал себя довольно капризным - а) одно неловкое движение, и он норовит свалиться с группировки хешированием на группировку сортировкой, убивая все заложенные в него мечты безумным external 2-way merge sort
б) при любом удобном случае пытается соскочить с bitmap index scan
(такое впечатление, что он троечник, и в школе слишком часто уроки прогуливал).

На фоне group by - inner join - не то, чтобы отличник, но уроков явно меньше прогулял.
Тверд, напорист и непокобелим.

Поэтому разговаривать с ним приходится практически матом - методом лишения его "любимых" индексов.
Тогда он приходит в легкое замешательство, но напористо пытается сделать лучшее из того, что "нам не задавали".
В целом молодец.

В зависимости от распределения данных, общие итоги наблюдения таковы:
join и intersect уверенно делят 1-2 место.
intersect нигде не опускается ниже второго, иногда выходя на первое.
Если join проиграл intersect-у, то с большой вероятностью проиграет и group by,
который, в свою очередь, в целом держится молодцом на 3м месте, несмотря на склонность к сортировке, иногда выходя на второе и опережая join.

Исходный вариант от Дейта с not exists( ... not exists...) и вариант с except не выдерживают конкуренции на больших объёмах.
(разница между вариантом Дейта и пропагандируемым Селко Group By в логике на краях -
у Дейта отсутствующим требованиям соответствуют все студенты, у Селко с group by - нет требований,
значит и студентов, им соответствующих, быть не может).

скрипты:
а) под победу inner join, который здесь правда неплох, и умно использует знание статистики:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
[SQL Fiddle][1]

**PostgreSQL 9.6 Schema Setup**:

    create table temp(ch_type varchar(40));
    create index ix_tmp on temp(ch_type);
    with t as (
      select ch_type 
      from unnest(Array['SMS', 'PUSH', 'POSTAL DOVE', 'POSTAL OFFICE', 'HOME EMAIL', 'WORK EMAIL'
                       ]) t(ch_type)
      )
    insert into temp(ch_type)
    Select ch_type from t;
    commit;
    create table person as select id from generate_series(1,500000) as g(id);
    alter table person add primary key (id);
    create table person_channel as select t.person_id, 
    case when inum = 1 then 'SMS' 
    when inum=2 then 'HOME EMAIL' 
    When inum=3 then 'FIXED' 
    when inum=4 then 'POSTAL DOVE' 
    when inum=5 then 'POSTAL OFFICE' 
    when inum=6 then 'WORK EMAIL' 
    else 'PUSH' end as channel_type 
    from ( Select random() as rnd, inum, p.id as person_id from generate_series(1,7) as g(inum), person p  
            where p. id < 600000
         ) t
     Where (rnd > 0.88 and inum = 7)
     Or (rnd > 0.67 and inum = 6)
     Or (rnd > 0.16 and inum = 5)
     or (rnd > 0.45 and inum = 4)
     or (rnd > 0.25 and inum = 3)
     or (rnd > 0.25 and inum = 2)
     or (rnd > 0.15 and inum = 1)
    ;
    create index person_channel_channel_type on person_channel(channel_type);
    create UNIQUE index uix_person_channel_p1 on person_channel(person_id, channel_type);
**Query 1**:

    explain analyze 
    select * from person p where
    exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='SMS')
    and exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='PUSH')
    and exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='POSTAL DOVE')
    and exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='POSTAL OFFICE')
    and exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='HOME EMAIL')
    and exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='WORK EMAIL')
    

**[Results][2]**:

    |                                                                                                                                                                                    QUERY PLAN |
    |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
    |                                                                           Nested Loop Semi Join  (cost=28066.15..70092.93 rows=5914 width=4) (actual time=220.019..458.080 rows=5700 loops=1) |
    |                                                                      ->  Nested Loop Semi Join  (cost=28065.72..65876.38 rows=6900 width=24) (actual time=219.891..438.146 rows=6678 loops=1) |
    |                                                                      ->  Nested Loop Semi Join  (cost=28065.29..60828.12 rows=8264 width=20) (actual time=219.884..412.323 rows=7942 loops=1) |
    |                                                                    ->  Nested Loop Semi Join  (cost=28064.87..54191.82 rows=10877 width=16) (actual time=219.867..380.768 rows=10627 loops=1) |
    |                                                                                ->  Hash Join  (cost=28064.44..42194.05 rows=19732 width=12) (actual time=219.824..287.889 rows=19595 loops=1) |
    |                                                                                                                                                            Hash Cond: (pc_5.person_id = p.id) |
    |                                                    ->  Bitmap Heap Scan on person_channel pc_5  (cost=3440.67..16768.97 rows=161064 width=4) (actual time=15.237..32.497 rows=164666 loops=1) |
    |                                                                                                                                             Recheck Cond: (channel_type = 'WORK EMAIL'::text) |
    |                                                                                                                                                                        Heap Blocks: exact=891 |
    |                                               ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..3400.41 rows=161064 width=0) (actual time=15.117..15.117 rows=164666 loops=1) |
    |                                                                                                                                               Index Cond: (channel_type = 'WORK EMAIL'::text) |
    |                                                                                      ->  Hash  (cost=23858.08..23858.08 rows=61255 width=8) (actual time=204.216..204.216 rows=60042 loops=1) |
    |                                                                                                                                              Buckets: 65536  Batches: 1  Memory Usage: 2858kB |
    |                                                                                  ->  Hash Join  (cost=14157.53..23858.08 rows=61255 width=8) (actual time=26.709..189.988 rows=60042 loops=1) |
    |                                                                                                                                                            Hash Cond: (p.id = pc_1.person_id) |
    |                                                                            ->  Seq Scan on person p  (cost=0.00..7213.00 rows=500000 width=4) (actual time=0.008..49.227 rows=500000 loops=1) |
    |                                                                                        ->  Hash  (cost=13391.84..13391.84 rows=61255 width=4) (actual time=26.374..26.374 rows=60042 loops=1) |
    |                                                                                                                                              Buckets: 65536  Batches: 1  Memory Usage: 2623kB |
    |                                                       ->  Bitmap Heap Scan on person_channel pc_1  (cost=1311.15..13391.84 rows=61255 width=4) (actual time=5.117..14.612 rows=60042 loops=1) |
    |                                                                                                                                                   Recheck Cond: (channel_type = 'PUSH'::text) |
    |                                                                                                                                                                        Heap Blocks: exact=325 |
    |                                                   ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..1295.84 rows=61255 width=0) (actual time=5.066..5.066 rows=60042 loops=1) |
    |                                                                                                                                                     Index Cond: (channel_type = 'PUSH'::text) |
    |                                        ->  Index Only Scan using uix_person_channel_p1 on person_channel pc_2  (cost=0.43..0.60 rows=1 width=4) (actual time=0.004..0.004 rows=1 loops=19595) |
    |                                                                                                                     Index Cond: ((person_id = p.id) AND (channel_type = 'POSTAL DOVE'::text)) |
    |                                                                                                                                                                           Heap Fetches: 10627 |
    |                                        ->  Index Only Scan using uix_person_channel_p1 on person_channel pc_4  (cost=0.43..0.60 rows=1 width=4) (actual time=0.003..0.003 rows=1 loops=10627) |
    |                                                                                                                      Index Cond: ((person_id = p.id) AND (channel_type = 'HOME EMAIL'::text)) |
    |                                                                                                                                                                            Heap Fetches: 7942 |
    |                                         ->  Index Only Scan using uix_person_channel_p1 on person_channel pc_3  (cost=0.43..0.60 rows=1 width=4) (actual time=0.003..0.003 rows=1 loops=7942) |
    |                                                                                                                   Index Cond: ((person_id = p.id) AND (channel_type = 'POSTAL OFFICE'::text)) |
    |                                                                                                                                                                            Heap Fetches: 6678 |
    |                                           ->  Index Only Scan using uix_person_channel_p1 on person_channel pc  (cost=0.43..0.60 rows=1 width=4) (actual time=0.003..0.003 rows=1 loops=6678) |
    |                                                                                                                             Index Cond: ((person_id = p.id) AND (channel_type = 'SMS'::text)) |
    |                                                                                                                                                                            Heap Fetches: 5700 |
    |                                                                                                                                                                       Planning time: 3.280 ms |
    |                                                                                                                                                                    Execution time: 458.830 ms |
**Query 2**:

    
    explain analyze 
    select * from person p where p.id in (
    select pc.person_id from person_channel pc where pc.channel_type='SMS'
    intersect all
    select pc.person_id from person_channel pc where pc.channel_type='PUSH'  
    intersect all
    select pc.person_id from person_channel pc where pc.channel_type='POSTAL DOVE'
    intersect all
    select pc.person_id from person_channel pc where pc.channel_type='POSTAL OFFICE'
    intersect all
    select pc.person_id from person_channel pc where pc.channel_type='HOME EMAIL'
    intersect all
    select pc.person_id from person_channel pc where pc.channel_type='WORK EMAIL'
    )

**[Results][3]**:

    |                                                                                                                                                                                                                                                    QUERY PLAN |
    |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
    |                                                                                                                                               Nested Loop  (cost=151617.97..153225.55 rows=250000 width=4) (actual time=1491.554..1525.070 rows=5700 loops=1) |
    |                                                                                                                                            ->  HashAggregate  (cost=151617.55..151619.55 rows=200 width=4) (actual time=1491.499..1492.539 rows=5700 loops=1) |
    |                                                                                                                                                                                                                           Group Key: "ANY_subquery".person_id |
    |                                                                                                                          ->  Subquery Scan on "ANY_subquery"  (cost=1311.15..151464.41 rows=61255 width=4) (actual time=1488.780..1490.224 rows=5700 loops=1) |
    |                                                                                                                                  ->  HashSetOp Intersect All  (cost=1311.15..150851.86 rows=61255 width=8) (actual time=1488.780..1489.673 rows=5700 loops=1) |
    |                                                                                                                                                ->  Append  (cost=1311.15..150296.06 rows=222319 width=8) (actual time=1397.917..1464.499 rows=182273 loops=1) |
    |                                                                                                                                                  ->  Result  (cost=1311.15..131916.45 rows=61255 width=8) (actual time=1397.917..1401.465 rows=17607 loops=1) |
    |                                                                                                                                 ->  HashSetOp Intersect All  (cost=1311.15..131303.90 rows=61255 width=8) (actual time=1397.915..1399.572 rows=17607 loops=1) |
    |                                                                                                                                                ->  Append  (cost=1311.15..130201.04 rows=441146 width=8) (actual time=1192.986..1340.540 rows=398773 loops=1) |
    |                                                                                                                                                  ->  Result  (cost=1311.15..102229.90 rows=61255 width=8) (actual time=1192.986..1197.226 rows=23540 loops=1) |
    |                                                                                                                                 ->  HashSetOp Intersect All  (cost=1311.15..101617.35 rows=61255 width=8) (actual time=1192.984..1194.804 rows=23540 loops=1) |
    |                                                                                                                                                 ->  Append  (cost=1311.15..100420.55 rows=478723 width=8) (actual time=904.696..1112.775 rows=448444 loops=1) |
    |                                                                                                                                                     ->  Result  (cost=1311.15..70800.71 rows=61255 width=8) (actual time=904.695..912.911 rows=27976 loops=1) |
    |                                                                                                                                    ->  HashSetOp Intersect All  (cost=1311.15..70188.16 rows=61255 width=8) (actual time=904.694..908.884 rows=27976 loops=1) |
    |                                                                                                                                                   ->  Append  (cost=1311.15..69346.00 rows=336867 width=8) (actual time=578.514..800.303 rows=326282 loops=1) |
    |                                                                                                                                                     ->  Result  (cost=1311.15..45945.30 rows=61255 width=8) (actual time=578.513..615.174 rows=51104 loops=1) |
    |                                                                                                                                    ->  HashSetOp Intersect All  (cost=1311.15..45332.75 rows=61255 width=8) (actual time=578.512..602.668 rows=51104 loops=1) |
    |                                                                                                                                                     ->  Append  (cost=1311.15..44108.18 rows=489829 width=8) (actual time=4.809..367.808 rows=485190 loops=1) |
    |                                                                                                                                 ->  Subquery Scan on "*SELECT* 2"  (cost=1311.15..14004.39 rows=61255 width=8) (actual time=4.809..19.132 rows=60042 loops=1) |
    |                                                                                                                         ->  Bitmap Heap Scan on person_channel pc  (cost=1311.15..13391.84 rows=61255 width=4) (actual time=4.808..13.006 rows=60042 loops=1) |
    |                                                                                                                                                                                                                   Recheck Cond: (channel_type = 'PUSH'::text) |
    |                                                                                                                                                                                                                                        Heap Blocks: exact=325 |
    |                                                                                                                   ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..1295.84 rows=61255 width=0) (actual time=4.576..4.576 rows=60042 loops=1) |
    |                                                                                                                                                                                                                     Index Cond: (channel_type = 'PUSH'::text) |
    |                                                                                                                             ->  Subquery Scan on "*SELECT* 1"  (cost=9145.88..30103.79 rows=428574 width=8) (actual time=56.818..251.698 rows=425148 loops=1) |
    |                                                                                                                   ->  Bitmap Heap Scan on person_channel pc_1  (cost=9145.88..25818.05 rows=428574 width=4) (actual time=56.817..163.670 rows=425148 loops=1) |
    |                                                                                                                                                                                                                    Recheck Cond: (channel_type = 'SMS'::text) |
    |                                                                                                                                                                                                                                       Heap Blocks: exact=1882 |
    |                                                                                                               ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..9038.73 rows=428574 width=0) (actual time=56.417..56.417 rows=425148 loops=1) |
    |                                                                                                                                                                                                                      Index Cond: (channel_type = 'SMS'::text) |
    |                                                                                                                             ->  Subquery Scan on "*SELECT* 3"  (cost=5884.42..23400.69 rows=275612 width=8) (actual time=44.969..149.994 rows=275178 loops=1) |
    |                                                                                                                   ->  Bitmap Heap Scan on person_channel pc_2  (cost=5884.42..20644.57 rows=275612 width=4) (actual time=44.968..104.955 rows=275178 loops=1) |
    |                                                                                                                                                                                                            Recheck Cond: (channel_type = 'POSTAL DOVE'::text) |
    |                                                                                                                                                                                                                                       Heap Blocks: exact=1488 |
    |                                                                                                               ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..5815.52 rows=275612 width=0) (actual time=44.667..44.667 rows=275178 loops=1) |
    |                                                                                                                                                                                                              Index Cond: (channel_type = 'POSTAL DOVE'::text) |
    |                                                                                                                             ->  Subquery Scan on "*SELECT* 4"  (cost=8911.80..29619.83 rows=417468 width=8) (actual time=60.305..165.563 rows=420468 loops=1) |
    |                                                                                                                   ->  Bitmap Heap Scan on person_channel pc_3  (cost=8911.80..25445.15 rows=417468 width=4) (actual time=60.303..119.995 rows=420468 loops=1) |
    |                                                                                                                                                                                                          Recheck Cond: (channel_type = 'POSTAL OFFICE'::text) |
    |                                                                                                                                                                                                                                       Heap Blocks: exact=2680 |
    |                                                                                                               ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..8807.44 rows=417468 width=0) (actual time=59.758..59.758 rows=420468 loops=1) |
    |                                                                                                                                                                                                            Index Cond: (channel_type = 'POSTAL OFFICE'::text) |
    |                                                                                                                             ->  Subquery Scan on "*SELECT* 5"  (cost=8108.58..27971.13 rows=379891 width=8) (actual time=31.709..114.545 rows=375233 loops=1) |
    |                                                                                                                    ->  Bitmap Heap Scan on person_channel pc_4  (cost=8108.58..24172.22 rows=379891 width=4) (actual time=31.708..76.635 rows=375233 loops=1) |
    |                                                                                                                                                                                                             Recheck Cond: (channel_type = 'HOME EMAIL'::text) |
    |                                                                                                                                                                                                                                       Heap Blocks: exact=2029 |
    |                                                                                                               ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..8013.61 rows=379891 width=0) (actual time=31.336..31.336 rows=375233 loops=1) |
    |                                                                                                                                                                                                               Index Cond: (channel_type = 'HOME EMAIL'::text) |
    |                                                                                                                              ->  Subquery Scan on "*SELECT* 6"  (cost=3440.67..18379.61 rows=161064 width=8) (actual time=13.145..50.188 rows=164666 loops=1) |
    |                                                                                                                    ->  Bitmap Heap Scan on person_channel pc_5  (cost=3440.67..16768.97 rows=161064 width=4) (actual time=13.145..33.970 rows=164666 loops=1) |
    |                                                                                                                                                                                                             Recheck Cond: (channel_type = 'WORK EMAIL'::text) |
    |                                                                                                                                                                                                                                        Heap Blocks: exact=891 |
    |                                                                                                               ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..3400.41 rows=161064 width=0) (actual time=13.033..13.033 rows=164666 loops=1) |
    |                                                                                                                                                                                                               Index Cond: (channel_type = 'WORK EMAIL'::text) |
    |                                                                                                                              ->  Index Only Scan using person_pkey on person p  (cost=0.42..8.02 rows=1 width=4) (actual time=0.005..0.005 rows=1 loops=5700) |
    |                                                                                                                                                                                                                   Index Cond: (id = "ANY_subquery".person_id) |
    |                                                                                                                                                                                                                                            Heap Fetches: 5700 |
    |                                                                                                                                                                                                                                       Planning time: 0.241 ms |
    |                                                                                                                                                                                                                                   Execution time: 1526.539 ms |
**Query 3**:

    
    explain --analyze 
    select p.* from person p
    where p.id in (
      select person_id 
      from unnest(Array['SMS', 'PUSH', 'POSTAL DOVE', 'POSTAL OFFICE', 'HOME EMAIL', 'WORK EMAIL'
                     ]) t(ch_type), 
           person_channel pc
    where  t.ch_type =  pc.channel_type
     group by pc.person_id
    having (
            select Count(*) 
            from unnest(Array['SMS', 'PUSH', 'POSTAL DOVE', 'POSTAL OFFICE', 'HOME EMAIL', 'WORK EMAIL'
                     ]) t(ch_type)
           ) 
           = Count(pc.channel_type)
    )
    

**[Results][4]**:

    |                                                                                               QUERY PLAN |
    |----------------------------------------------------------------------------------------------------------|
    |                                         Merge Semi Join  (cost=352709.52..401100.99 rows=250000 width=4) |
    |                                                                        Merge Cond: (p.id = pc.person_id) |
    |             ->  Index Only Scan using person_pkey on person p  (cost=0.42..15212.42 rows=500000 width=4) |
    |                                         ->  Materialize  (cost=352709.10..378847.80 rows=463262 width=4) |
    |                                      ->  GroupAggregate  (cost=352709.10..373057.02 rows=463262 width=4) |
    |                                                                                  Group Key: pc.person_id |
    |                                                                    Filter: ($0 = count(pc.channel_type)) |
    |                                                                                  InitPlan 1 (returns $0) |
    |                                                          ->  Aggregate  (cost=1.25..1.26 rows=1 width=8) |
    |                                      ->  Function Scan on unnest t_1  (cost=0.00..1.00 rows=100 width=0) |
    |                                              ->  Sort  (cost=352707.83..357946.27 rows=2095374 width=13) |
    |                                                                                   Sort Key: pc.person_id |
    |                                               ->  Hash Join  (cost=2.25..61082.39 rows=2095374 width=13) |
    |                                                                 Hash Cond: (pc.channel_type = t.ch_type) |
    |                           ->  Seq Scan on person_channel pc  (cost=0.00..32268.74 rows=2095374 width=13) |
    |                                                            ->  Hash  (cost=1.00..1.00 rows=100 width=32) |
    |                                       ->  Function Scan on unnest t  (cost=0.00..1.00 rows=100 width=32) |
**Query 4**:

    
    explain --analyze 
    select p.* from person p
    where not exists(
        select * From temp t
        where not exists(
           select * from person_channel pc
           where   t.ch_type = pc.channel_type
              and  p.id = pc.person_id
        )
    )

**[Results][5]**:

    |                                                                                                 QUERY PLAN |
    |------------------------------------------------------------------------------------------------------------|
    |                                      Nested Loop Anti Join  (cost=0.00..1357830633.53 rows=250000 width=4) |
    |                                                                             Join Filter: (NOT (SubPlan 1)) |
    |                                         ->  Seq Scan on person p  (cost=0.00..7213.00 rows=500000 width=4) |
    |                                                      ->  Materialize  (cost=0.00..19.60 rows=640 width=98) |
    |                                               ->  Seq Scan on temp t  (cost=0.00..16.40 rows=640 width=98) |
    |                                                                                                  SubPlan 1 |
    |     ->  Index Only Scan using uix_person_channel_p1 on person_channel pc  (cost=0.43..8.45 rows=1 width=0) |
    |                                    Index Cond: ((person_id = p.id) AND (channel_type = (t.ch_type)::text)) |
**Query 5**:

    
    explain --analyze 
    select p.* from person p
    where p.id = any (
      select person_id 
      from person_channel pc, temp t
    where  t.ch_type =  pc.channel_type
     group by pc.person_id
    having (select Count(*) from temp) = Count(t.ch_type) --Count(t.channel_type)
    )

**[Results][6]**:

    |                                                                                                                             QUERY PLAN |
    |----------------------------------------------------------------------------------------------------------------------------------------|
    |                                                                           Merge Semi Join  (cost=19.01..661846.48 rows=250000 width=4) |
    |                                                                                                      Merge Cond: (p.id = pc.person_id) |
    |                                           ->  Index Only Scan using person_pkey on person p  (cost=0.42..15212.42 rows=500000 width=4) |
    |                                                                           ->  Materialize  (cost=18.59..639593.29 rows=463262 width=4) |
    |                                                                        ->  GroupAggregate  (cost=18.59..633802.51 rows=463262 width=4) |
    |                                                                                                                Group Key: pc.person_id |
    |                                                                                                        Filter: ($0 = count(t.ch_type)) |
    |                                                                                                                InitPlan 1 (returns $0) |
    |                                                                                      ->  Aggregate  (cost=18.00..18.01 rows=1 width=8) |
    |                                                                              ->  Seq Scan on temp  (cost=0.00..16.40 rows=640 width=0) |
    |                                                                         ->  Nested Loop  (cost=0.58..595625.90 rows=6705197 width=102) |
    |                     ->  Index Only Scan using uix_person_channel_p1 on person_channel pc  (cost=0.43..108403.44 rows=2095374 width=13) |
    |                                                          ->  Index Only Scan using ix_tmp on temp t  (cost=0.15..0.20 rows=3 width=98) |
    |                                                                                                Index Cond: (ch_type = pc.channel_type) |
**Query 6**:

    
    explain analyze 
    select p.* from person p
    where p.id = any (
      select person_id 
      from person_channel pc
    where  pc.channel_type in ('SMS', 'PUSH', 'POSTAL DOVE', 'POSTAL OFFICE', 'HOME EMAIL', 'WORK EMAIL')
     group by pc.person_id
    having 6 = Count(pc.channel_type)
    )
    

**[Results][7]**:

    |                                                                                                                                                                          QUERY PLAN |
    |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
    |                                                                         Merge Semi Join  (cost=0.85..165408.18 rows=250000 width=4) (actual time=0.863..1553.633 rows=5700 loops=1) |
    |                                                                                                                                                   Merge Cond: (p.id = pc.person_id) |
    |                                       ->  Index Only Scan using person_pkey on person p  (cost=0.42..15212.42 rows=500000 width=4) (actual time=0.021..102.478 rows=499974 loops=1) |
    |                                                                                                                                                                Heap Fetches: 499974 |
    |                                                                         ->  Materialize  (cost=0.43..143157.30 rows=463077 width=4) (actual time=0.778..1418.156 rows=5700 loops=1) |
    |                                                                      ->  GroupAggregate  (cost=0.43..137368.84 rows=463077 width=4) (actual time=0.778..1416.940 rows=5700 loops=1) |
    |                                                                                                                                                             Group Key: pc.person_id |
    |                                                                                                                                                Filter: (6 = count(pc.channel_type)) |
    |                                                                                                                                                      Rows Removed by Filter: 493544 |
    |               ->  Index Only Scan using uix_person_channel_p1 on person_channel pc  (cost=0.43..124118.75 rows=1723864 width=13) (actual time=0.023..1128.949 rows=1720735 loops=1) |
    |                                                                         Filter: (channel_type = ANY ('{SMS,PUSH,"POSTAL DOVE","POSTAL OFFICE","HOME EMAIL","WORK EMAIL"}'::text[])) |
    |                                                                                                                                                      Rows Removed by Filter: 374639 |
    |                                                                                                                                                               Heap Fetches: 2095374 |
    |                                                                                                                                                             Planning time: 0.209 ms |
    |                                                                                                                                                         Execution time: 1554.072 ms |




Под не победу inner join.
Он держится, то, что здесь если уж join, то желателен hash join - до него дошло.
Но финту-другому его то ли недоучили, то ли сам прогулял.
Зато group by перестаёт нервически реагировать на окружающую среду и, наконец, хотя бы приблизительно соображает, что же от него на самом деле требуется.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
**PostgreSQL 9.6 Schema Setup**:

    create table temp(ch_type varchar(40));
    with t as (
      select ch_type 
      from unnest(Array['SMS', 'PUSH', 'POSTAL DOVE', 'POSTAL OFFICE', 'HOME EMAIL', 'WORK EMAIL'
                       ]) t(ch_type)
      )
    insert into temp(ch_type)
    Select ch_type from t;
    commit;
    create table person as select id from generate_series(1,500000) as g(id);
    alter table person add primary key (id);
    create table person_channel as select t.person_id, 
    case when inum = 1 then 'SMS' 
    when inum=2 then 'HOME EMAIL' 
    When inum=3 then 'FIXED' 
    when inum=4 then 'POSTAL DOVE' 
    when inum=5 then 'POSTAL OFFICE' 
    when inum=6 then 'WORK EMAIL' 
    else 'PUSH' end as channel_type 
    from ( Select random() as rnd, inum, p.id as person_id from generate_series(1,7) as g(inum), person p  
            where p. id < 600000
         ) t
     Where (rnd > 0.88 and inum = 7)
     Or (rnd > 0.67 and inum = 6)
     Or (rnd > 0.16 and inum = 5)
     or (rnd > 0.45 and inum = 4)
     or (rnd > 0.25 and inum = 3)
     or (rnd > 0.25 and inum = 2)
     or (rnd > 0.15 and inum = 1)
    ;
    create index person_channel_channel_type on person_channel(channel_type);
    -- подставляем для данной задачи неудачный индекс, в норме он должен быть проигнорирован оптимизатором
    create UNIQUE index uix_person_channel_p2 on person_channel(channel_type, person_id);
**Query 1**:

    explain analyze 
    select * from person p where
    exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='SMS')
    and exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='PUSH')
    and exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='POSTAL DOVE')
    and exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='POSTAL OFFICE')
    and exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='HOME EMAIL')
    and exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='WORK EMAIL')
    

**[Results][2]**:

    |                                                                                                                                                                                QUERY PLAN |
    |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
    |                                                                                  Hash Join  (cost=72268.11..83378.84 rows=7812 width=4) (actual time=793.786..1337.321 rows=5915 loops=1) |
    |                                                                                                                                                        Hash Cond: (p.id = pc_5.person_id) |
    |                                                                           ->  Hash Join  (cost=60223.42..71272.28 rows=15625 width=24) (actual time=726.830..1255.894 rows=17741 loops=1) |
    |                                                                                                                                                        Hash Cond: (p.id = pc_4.person_id) |
    |                                                                           ->  Hash Join  (cost=48178.74..59103.86 rows=31250 width=20) (actual time=566.295..1045.017 rows=23642 loops=1) |
    |                                                                                                                                                        Hash Cond: (p.id = pc_3.person_id) |
    |                                                                            ->  Hash Join  (cost=36134.05..46811.70 rows=62500 width=16) (actual time=394.299..818.651 rows=28132 loops=1) |
    |                                                                                                                                                        Hash Cond: (p.id = pc_2.person_id) |
    |                                                                           ->  Hash Join  (cost=24089.37..34272.07 rows=125000 width=12) (actual time=265.827..649.390 rows=51347 loops=1) |
    |                                                                                                                                                        Hash Cond: (p.id = pc_1.person_id) |
    |                                                                           ->  Hash Join  (cost=12044.68..21237.48 rows=250000 width=8) (actual time=232.323..517.206 rows=425354 loops=1) |
    |                                                                                                                                                          Hash Cond: (p.id = pc.person_id) |
    |                                                                        ->  Seq Scan on person p  (cost=0.00..7213.00 rows=500000 width=4) (actual time=0.023..52.159 rows=500000 loops=1) |
    |                                                                                 ->  Hash  (cost=11913.68..11913.68 rows=10480 width=4) (actual time=232.138..232.138 rows=425354 loops=1) |
    |                                                                                                       Buckets: 131072 (originally 16384)  Batches: 8 (originally 1)  Memory Usage: 3073kB |
    |                                                   ->  Bitmap Heap Scan on person_channel pc  (cost=225.65..11913.68 rows=10480 width=4) (actual time=58.802..140.496 rows=425354 loops=1) |
    |                                                                                                                                                Recheck Cond: (channel_type = 'SMS'::text) |
    |                                                                                                                                                                   Heap Blocks: exact=1883 |
    |                                             ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..223.03 rows=10480 width=0) (actual time=58.393..58.393 rows=425354 loops=1) |
    |                                                                                                                                                  Index Cond: (channel_type = 'SMS'::text) |
    |                                                                                    ->  Hash  (cost=11913.68..11913.68 rows=10480 width=4) (actual time=33.440..33.441 rows=60351 loops=1) |
    |                                                                                                        Buckets: 65536 (originally 16384)  Batches: 1 (originally 1)  Memory Usage: 2634kB |
    |                                                    ->  Bitmap Heap Scan on person_channel pc_1  (cost=225.65..11913.68 rows=10480 width=4) (actual time=5.756..19.768 rows=60351 loops=1) |
    |                                                                                                                                               Recheck Cond: (channel_type = 'PUSH'::text) |
    |                                                                                                                                                                    Heap Blocks: exact=327 |
    |                                                ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..223.03 rows=10480 width=0) (actual time=5.680..5.680 rows=60351 loops=1) |
    |                                                                                                                                                 Index Cond: (channel_type = 'PUSH'::text) |
    |                                                                                 ->  Hash  (cost=11913.68..11913.68 rows=10480 width=4) (actual time=128.408..128.408 rows=274803 loops=1) |
    |                                                                                                       Buckets: 131072 (originally 16384)  Batches: 4 (originally 1)  Memory Usage: 3442kB |
    |                                                  ->  Bitmap Heap Scan on person_channel pc_2  (cost=225.65..11913.68 rows=10480 width=4) (actual time=24.369..74.077 rows=274803 loops=1) |
    |                                                                                                                                        Recheck Cond: (channel_type = 'POSTAL DOVE'::text) |
    |                                                                                                                                                                   Heap Blocks: exact=1486 |
    |                                             ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..223.03 rows=10480 width=0) (actual time=24.148..24.148 rows=274803 loops=1) |
    |                                                                                                                                          Index Cond: (channel_type = 'POSTAL DOVE'::text) |
    |                                                                                 ->  Hash  (cost=11913.68..11913.68 rows=10480 width=4) (actual time=171.916..171.916 rows=419867 loops=1) |
    |                                                                                                       Buckets: 131072 (originally 16384)  Batches: 8 (originally 1)  Memory Usage: 3073kB |
    |                                                 ->  Bitmap Heap Scan on person_channel pc_3  (cost=225.65..11913.68 rows=10480 width=4) (actual time=39.695..104.616 rows=419867 loops=1) |
    |                                                                                                                                      Recheck Cond: (channel_type = 'POSTAL OFFICE'::text) |
    |                                                                                                                                                                   Heap Blocks: exact=2675 |
    |                                             ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..223.03 rows=10480 width=0) (actual time=39.203..39.203 rows=419867 loops=1) |
    |                                                                                                                                        Index Cond: (channel_type = 'POSTAL OFFICE'::text) |
    |                                                                                 ->  Hash  (cost=11913.68..11913.68 rows=10480 width=4) (actual time=160.503..160.503 rows=375413 loops=1) |
    |                                                                                                       Buckets: 131072 (originally 16384)  Batches: 8 (originally 1)  Memory Usage: 3073kB |
    |                                                  ->  Bitmap Heap Scan on person_channel pc_4  (cost=225.65..11913.68 rows=10480 width=4) (actual time=35.946..95.224 rows=375413 loops=1) |
    |                                                                                                                                         Recheck Cond: (channel_type = 'HOME EMAIL'::text) |
    |                                                                                                                                                                   Heap Blocks: exact=2030 |
    |                                             ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..223.03 rows=10480 width=0) (actual time=35.542..35.542 rows=375413 loops=1) |
    |                                                                                                                                           Index Cond: (channel_type = 'HOME EMAIL'::text) |
    |                                                                                   ->  Hash  (cost=11913.68..11913.68 rows=10480 width=4) (actual time=66.818..66.818 rows=165541 loops=1) |
    |                                                                                                       Buckets: 131072 (originally 16384)  Batches: 2 (originally 1)  Memory Usage: 3935kB |
    |                                                  ->  Bitmap Heap Scan on person_channel pc_5  (cost=225.65..11913.68 rows=10480 width=4) (actual time=15.162..39.784 rows=165541 loops=1) |
    |                                                                                                                                         Recheck Cond: (channel_type = 'WORK EMAIL'::text) |
    |                                                                                                                                                                    Heap Blocks: exact=896 |
    |                                             ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..223.03 rows=10480 width=0) (actual time=15.041..15.041 rows=165541 loops=1) |
    |                                                                                                                                           Index Cond: (channel_type = 'WORK EMAIL'::text) |
    |                                                                                                                                                                   Planning time: 5.952 ms |
    |                                                                                                                                                               Execution time: 1338.166 ms |
**Query 2**:

    
    explain analyze 
    select * from person p where p.id = any (
    select pc.person_id from person_channel pc where pc.channel_type='SMS'
    intersect
    select pc.person_id from person_channel pc where pc.channel_type='PUSH'  
    intersect
    select pc.person_id from person_channel pc where pc.channel_type='POSTAL DOVE'
    intersect
    select pc.person_id from person_channel pc where pc.channel_type='POSTAL OFFICE'
    intersect
    select pc.person_id from person_channel pc where pc.channel_type='HOME EMAIL'
    intersect
    select pc.person_id from person_channel pc where pc.channel_type='WORK EMAIL'
    )

**[Results][3]**:

    |                                                                                                                                                                                                                                            QUERY PLAN |
    |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
    |                                                                                                                                           Nested Loop  (cost=226.07..73886.11 rows=250000 width=4) (actual time=1147.051..1479.907 rows=5915 loops=1) |
    |                                                                                                                      ->  Subquery Scan on "ANY_subquery"  (cost=225.65..72280.11 rows=200 width=4) (actual time=1146.389..1149.020 rows=5915 loops=1) |
    |                                                                                                                                  ->  HashSetOp Intersect  (cost=225.65..72278.11 rows=200 width=8) (actual time=1146.388..1148.182 rows=5915 loops=1) |
    |                                                                                                                                           ->  Append  (cost=225.65..72251.41 rows=10680 width=8) (actual time=1052.638..1119.847 rows=183282 loops=1) |
    |                                                                                                                                              ->  Result  (cost=225.65..60232.92 rows=200 width=8) (actual time=1052.637..1056.055 rows=17741 loops=1) |
    |                                                                                                                                 ->  HashSetOp Intersect  (cost=225.65..60230.92 rows=200 width=8) (actual time=1052.636..1054.131 rows=17741 loops=1) |
    |                                                                                                                                             ->  Append  (cost=225.65..60204.22 rows=10680 width=8) (actual time=841.281..991.040 rows=399055 loops=1) |
    |                                                                                                                                                ->  Result  (cost=225.65..48185.74 rows=200 width=8) (actual time=841.280..845.769 rows=23642 loops=1) |
    |                                                                                                                                   ->  HashSetOp Intersect  (cost=225.65..48183.74 rows=200 width=8) (actual time=841.279..843.246 rows=23642 loops=1) |
    |                                                                                                                                             ->  Append  (cost=225.65..48157.04 rows=10680 width=8) (actual time=601.620..764.311 rows=447999 loops=1) |
    |                                                                                                                                                ->  Result  (cost=225.65..36138.55 rows=200 width=8) (actual time=601.619..608.973 rows=28132 loops=1) |
    |                                                                                                                                   ->  HashSetOp Intersect  (cost=225.65..36136.55 rows=200 width=8) (actual time=601.618..605.849 rows=28132 loops=1) |
    |                                                                                                                                             ->  Append  (cost=225.65..36109.85 rows=10680 width=8) (actual time=378.483..526.082 rows=326150 loops=1) |
    |                                                                                                                                                ->  Result  (cost=225.65..24091.37 rows=200 width=8) (actual time=378.483..428.020 rows=51347 loops=1) |
    |                                                                                                                                   ->  HashSetOp Intersect  (cost=225.65..24089.37 rows=200 width=8) (actual time=378.482..421.484 rows=51347 loops=1) |
    |                                                                                                                                              ->  Append  (cost=225.65..24036.97 rows=20960 width=8) (actual time=28.558..169.794 rows=485705 loops=1) |
    |                                                                                                                       ->  Subquery Scan on "*SELECT* 1"  (cost=225.65..12018.48 rows=10480 width=8) (actual time=28.557..116.940 rows=425354 loops=1) |
    |                                                                                                                ->  Bitmap Heap Scan on person_channel pc  (cost=225.65..11913.68 rows=10480 width=4) (actual time=28.557..75.686 rows=425354 loops=1) |
    |                                                                                                                                                                                                            Recheck Cond: (channel_type = 'SMS'::text) |
    |                                                                                                                                                                                                                               Heap Blocks: exact=1883 |
    |                                                                                                         ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..223.03 rows=10480 width=0) (actual time=28.310..28.310 rows=425354 loops=1) |
    |                                                                                                                                                                                                              Index Cond: (channel_type = 'SMS'::text) |
    |                                                                                                                          ->  Subquery Scan on "*SELECT* 2"  (cost=225.65..12018.48 rows=10480 width=8) (actual time=3.851..16.094 rows=60351 loops=1) |
    |                                                                                                                ->  Bitmap Heap Scan on person_channel pc_1  (cost=225.65..11913.68 rows=10480 width=4) (actual time=3.849..10.304 rows=60351 loops=1) |
    |                                                                                                                                                                                                           Recheck Cond: (channel_type = 'PUSH'::text) |
    |                                                                                                                                                                                                                                Heap Blocks: exact=327 |
    |                                                                                                            ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..223.03 rows=10480 width=0) (actual time=3.811..3.811 rows=60351 loops=1) |
    |                                                                                                                                                                                                             Index Cond: (channel_type = 'PUSH'::text) |
    |                                                                                                                        ->  Subquery Scan on "*SELECT* 3"  (cost=225.65..12018.48 rows=10480 width=8) (actual time=17.917..74.476 rows=274803 loops=1) |
    |                                                                                                              ->  Bitmap Heap Scan on person_channel pc_2  (cost=225.65..11913.68 rows=10480 width=4) (actual time=17.915..47.682 rows=274803 loops=1) |
    |                                                                                                                                                                                                    Recheck Cond: (channel_type = 'POSTAL DOVE'::text) |
    |                                                                                                                                                                                                                               Heap Blocks: exact=1486 |
    |                                                                                                         ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..223.03 rows=10480 width=0) (actual time=17.719..17.719 rows=274803 loops=1) |
    |                                                                                                                                                                                                      Index Cond: (channel_type = 'POSTAL DOVE'::text) |
    |                                                                                                                       ->  Subquery Scan on "*SELECT* 4"  (cost=225.65..12018.48 rows=10480 width=8) (actual time=32.925..123.173 rows=419867 loops=1) |
    |                                                                                                              ->  Bitmap Heap Scan on person_channel pc_3  (cost=225.65..11913.68 rows=10480 width=4) (actual time=32.923..81.506 rows=419867 loops=1) |
    |                                                                                                                                                                                                  Recheck Cond: (channel_type = 'POSTAL OFFICE'::text) |
    |                                                                                                                                                                                                                               Heap Blocks: exact=2675 |
    |                                                                                                         ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..223.03 rows=10480 width=0) (actual time=32.515..32.515 rows=419867 loops=1) |
    |                                                                                                                                                                                                    Index Cond: (channel_type = 'POSTAL OFFICE'::text) |
    |                                                                                                                       ->  Subquery Scan on "*SELECT* 5"  (cost=225.65..12018.48 rows=10480 width=8) (actual time=29.675..117.075 rows=375413 loops=1) |
    |                                                                                                              ->  Bitmap Heap Scan on person_channel pc_4  (cost=225.65..11913.68 rows=10480 width=4) (actual time=29.673..80.562 rows=375413 loops=1) |
    |                                                                                                                                                                                                     Recheck Cond: (channel_type = 'HOME EMAIL'::text) |
    |                                                                                                                                                                                                                               Heap Blocks: exact=2030 |
    |                                                                                                         ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..223.03 rows=10480 width=0) (actual time=29.380..29.380 rows=375413 loops=1) |
    |                                                                                                                                                                                                       Index Cond: (channel_type = 'HOME EMAIL'::text) |
    |                                                                                                                        ->  Subquery Scan on "*SELECT* 6"  (cost=225.65..12018.48 rows=10480 width=8) (actual time=12.978..50.747 rows=165541 loops=1) |
    |                                                                                                              ->  Bitmap Heap Scan on person_channel pc_5  (cost=225.65..11913.68 rows=10480 width=4) (actual time=12.976..34.436 rows=165541 loops=1) |
    |                                                                                                                                                                                                     Recheck Cond: (channel_type = 'WORK EMAIL'::text) |
    |                                                                                                                                                                                                                                Heap Blocks: exact=896 |
    |                                                                                                         ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..223.03 rows=10480 width=0) (actual time=12.865..12.865 rows=165541 loops=1) |
    |                                                                                                                                                                                                       Index Cond: (channel_type = 'WORK EMAIL'::text) |
    |                                                                                                                      ->  Index Only Scan using person_pkey on person p  (cost=0.42..8.02 rows=1 width=4) (actual time=0.055..0.056 rows=1 loops=5915) |
    |                                                                                                                                                                                                           Index Cond: (id = "ANY_subquery".person_id) |
    |                                                                                                                                                                                                                                    Heap Fetches: 5915 |
    |                                                                                                                                                                                                                               Planning time: 0.216 ms |
    |                                                                                                                                                                                                                           Execution time: 1482.585 ms |
**Query 3**:

      
    explain analyze 
    select p.* from person p
    where p.id in (
      select person_id 
      from unnest(Array['SMS', 'PUSH', 'POSTAL DOVE', 'POSTAL OFFICE', 'HOME EMAIL', 'WORK EMAIL'
                     ]) t(ch_type), 
           person_channel pc
    where  t.ch_type =  pc.channel_type
     group by pc.person_id
    having (
            select Count(*) 
            from unnest(Array['SMS', 'PUSH', 'POSTAL DOVE', 'POSTAL OFFICE', 'HOME EMAIL', 'WORK EMAIL'
                     ]) t(ch_type)
           ) 
           = Count(pc.channel_type)
    )
    

**[Results][4]**:

    |                                                                                                                                     QUERY PLAN |
    |------------------------------------------------------------------------------------------------------------------------------------------------|
    |                                  Nested Loop  (cost=55863.85..57473.43 rows=250000 width=4) (actual time=1497.495..1689.632 rows=5915 loops=1) |
    |                               ->  HashAggregate  (cost=55863.43..55865.43 rows=200 width=4) (actual time=1497.479..1660.463 rows=5915 loops=1) |
    |                                                                                                                        Group Key: pc.person_id |
    |                                                                                                          Filter: ($0 = count(pc.channel_type)) |
    |                                                                                                                 Rows Removed by Filter: 493285 |
    |                                                                                                                        InitPlan 1 (returns $0) |
    |                                                      ->  Aggregate  (cost=1.25..1.26 rows=1 width=8) (actual time=0.015..0.015 rows=1 loops=1) |
    |                                  ->  Function Scan on unnest t_1  (cost=0.00..1.00 rows=100 width=0) (actual time=0.012..0.012 rows=6 loops=1) |
    |                                   ->  Hash Join  (cost=2.25..50621.94 rows=1048045 width=36) (actual time=0.035..673.687 rows=1721329 loops=1) |
    |                                                                                                       Hash Cond: (pc.channel_type = t.ch_type) |
    |               ->  Seq Scan on person_channel pc  (cost=0.00..32278.90 rows=2096090 width=36) (actual time=0.012..193.675 rows=2096090 loops=1) |
    |                                                        ->  Hash  (cost=1.00..1.00 rows=100 width=32) (actual time=0.009..0.009 rows=6 loops=1) |
    |                                                                                                   Buckets: 1024  Batches: 1  Memory Usage: 9kB |
    |                                   ->  Function Scan on unnest t  (cost=0.00..1.00 rows=100 width=32) (actual time=0.006..0.006 rows=6 loops=1) |
    |               ->  Index Only Scan using person_pkey on person p  (cost=0.42..8.02 rows=1 width=4) (actual time=0.004..0.004 rows=1 loops=5915) |
    |                                                                                                                Index Cond: (id = pc.person_id) |
    |                                                                                                                             Heap Fetches: 5915 |
    |                                                                                                                        Planning time: 1.093 ms |
    |                                                                                                                    Execution time: 1692.943 ms |
**Query 4**:

    
    explain analyze 
    select p.* from person p
    where p.id = any (
      select person_id 
      from person_channel pc
    where  pc.channel_type in ('SMS', 'PUSH', 'POSTAL DOVE', 'POSTAL OFFICE', 'HOME EMAIL', 'WORK EMAIL')
     group by pc.person_id
    having 6 = Count(pc.channel_type)
    )
    

**[Results][5]**:

    |                                                                                                                                                      QUERY PLAN |
    |-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
    |                                                   Nested Loop  (cost=14075.18..15684.75 rows=250000 width=4) (actual time=1122.610..1330.417 rows=5915 loops=1) |
    |                                                ->  HashAggregate  (cost=14074.75..14076.75 rows=200 width=4) (actual time=1122.586..1299.000 rows=5915 loops=1) |
    |                                                                                                                                         Group Key: pc.person_id |
    |                                                                                                                            Filter: (6 = count(pc.channel_type)) |
    |                                                                                                                                  Rows Removed by Filter: 493285 |
    |                     ->  Bitmap Heap Scan on person_channel pc  (cost=1341.89..13760.34 rows=62883 width=36) (actual time=142.723..324.567 rows=1721329 loops=1) |
    |                                               Recheck Cond: (channel_type = ANY ('{SMS,PUSH,"POSTAL DOVE","POSTAL OFFICE","HOME EMAIL","WORK EMAIL"}'::text[])) |
    |                                                                                                                                         Heap Blocks: exact=9293 |
    |               ->  Bitmap Index Scan on person_channel_channel_type  (cost=0.00..1326.16 rows=62883 width=0) (actual time=141.004..141.004 rows=1721329 loops=1) |
    |                                                 Index Cond: (channel_type = ANY ('{SMS,PUSH,"POSTAL DOVE","POSTAL OFFICE","HOME EMAIL","WORK EMAIL"}'::text[])) |
    |                                ->  Index Only Scan using person_pkey on person p  (cost=0.42..8.02 rows=1 width=4) (actual time=0.005..0.005 rows=1 loops=5915) |
    |                                                                                                                                 Index Cond: (id = pc.person_id) |
    |                                                                                                                                              Heap Fetches: 5915 |
    |                                                                                                                                         Planning time: 0.235 ms |
    |                                                                                                                                     Execution time: 1332.619 ms |

...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079707
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby,

О вот это уже серьезный аргументированный ответ!
Изучу завтра уже на свежую голову.


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079709
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На какой-же синтетике вы гоняете ваши бенчмарки. На табличках из 1-й колонки?

А бедняга автор затащит это себе где 1 datarow равен блоку
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079714
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton
На какой-же синтетике вы гоняете ваши бенчмарки. На табличках из 1-й колонки?

А бедняга автор затащит это себе где 1 datarow равен блоку


Если не забыть vacuum analyze после загрузки данных сделать - там IOS (index only scan) идет на всех exists ветках
и на размер собственно datarow у person_channel вообще пофигу (да и на размер datatow у person по большому счёту тоже).

Вот как план выглядит на современной 13 версии базы (а не 9.6 которой 5 лет и которая EOL в сентябре) на данных от booby (вторая версия индекса)
где сделан всетаки vacuum analyze после заливки данных.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
test=#     explain analyze 
    select * from person p where
    exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='SMS')
    and exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='PUSH')
    and exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='POSTAL DOVE')
    and exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='POSTAL OFFICE')
    and exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='HOME EMAIL')
    and exists (select null from person_channel pc where p.id = pc.person_id and pc.channel_type='WORK EMAIL');
                                                                                            QUERY PLAN                                                                                            
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop  (cost=2.99..34922.10 rows=5584 width=4) (actual time=0.416..283.539 rows=5797 loops=1)
   ->  Nested Loop  (cost=2.57..32273.85 rows=5846 width=24) (actual time=0.392..266.937 rows=5797 loops=1)
         ->  Nested Loop  (cost=2.14..28620.96 rows=6974 width=20) (actual time=0.345..233.344 rows=6911 loops=1)
               Join Filter: (pc_1.person_id = pc.person_id)
               ->  Nested Loop  (cost=1.71..24165.97 rows=8173 width=16) (actual time=0.302..194.197 rows=8114 loops=1)
                     Join Filter: (pc_1.person_id = pc_4.person_id)
                     ->  Merge Join  (cost=1.28..18007.48 rows=10684 width=12) (actual time=0.276..142.428 rows=10893 loops=1)
                           Merge Cond: (pc_1.person_id = pc_2.person_id)
                           ->  Merge Join  (cost=0.85..8044.59 rows=19110 width=8) (actual time=0.232..65.693 rows=19941 loops=1)
                                 Merge Cond: (pc_1.person_id = pc_5.person_id)
                                 ->  Index Only Scan using uix_person_channel_p2 on person_channel pc_1  (cost=0.43..1897.74 rows=57675 width=4) (actual time=0.147..12.164 rows=60288 loops=1)
                                       Index Cond: (channel_type = 'PUSH'::text)
                                       Heap Fetches: 0
                                 ->  Index Only Scan using uix_person_channel_p2 on person_channel pc_5  (cost=0.43..5401.17 rows=164157 width=4) (actual time=0.074..31.798 rows=164698 loops=1)
                                       Index Cond: (channel_type = 'WORK EMAIL'::text)
                                       Heap Fetches: 0
                           ->  Index Only Scan using uix_person_channel_p2 on person_channel pc_2  (cost=0.43..9115.79 rows=276992 width=4) (actual time=0.039..52.651 rows=275011 loops=1)
                                 Index Cond: (channel_type = 'POSTAL DOVE'::text)
                                 Heap Fetches: 0
                     ->  Index Only Scan using uix_person_channel_p2 on person_channel pc_4  (cost=0.43..0.56 rows=1 width=4) (actual time=0.004..0.004 rows=1 loops=10893)
                           Index Cond: ((channel_type = 'HOME EMAIL'::text) AND (person_id = pc_2.person_id))
                           Heap Fetches: 0
               ->  Index Only Scan using uix_person_channel_p2 on person_channel pc  (cost=0.43..0.53 rows=1 width=4) (actual time=0.004..0.004 rows=1 loops=8114)
                     Index Cond: ((channel_type = 'SMS'::text) AND (person_id = pc_4.person_id))
                     Heap Fetches: 0
         ->  Index Only Scan using uix_person_channel_p2 on person_channel pc_3  (cost=0.43..0.52 rows=1 width=4) (actual time=0.004..0.004 rows=1 loops=6911)
               Index Cond: ((channel_type = 'POSTAL OFFICE'::text) AND (person_id = pc.person_id))
               Heap Fetches: 0
   ->  Index Only Scan using person_pkey on person p  (cost=0.42..0.45 rows=1 width=4) (actual time=0.002..0.002 rows=1 loops=5797)
         Index Cond: (id = pc.person_id)
         Heap Fetches: 0
 Planning Time: 22.541 ms
 Execution Time: 284.087 ms
(33 rows)



Тут за счет IOS и умного использования статистики - тут вариант с exists выигрывает у всех подряд.
На второй версии индекса - результат несколько отличается по скорости но всеравно в пределах 300ms.

В принципе добавить 2kb случайного payload в обе таблицы не сложно но это уже дело для завтра.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079721
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton
На какой-же синтетике вы гоняете ваши бенчмарки. На табличках из 1-й колонки?

А бедняга автор затащит это себе где 1 datarow равен блоку

Так пузами только на синтетике и меряются.
А еще обязательно на прогретых данных, и в одно рыло, без конкуренции за диски и процессор.
А иначе всё колыхаться будет и оспариваться.
В данном случае синтетический person приводит лишь к тому, что системе до лампады, как по нему бежать - по индексу или нет.
Это имеет для данной задачи минорное значение. Основные шашки вокруг работы с person_channel рубятся.

2Maxim Boguk
сдаётся, что маловато данных для конкретного окружения.
Индекс коротковат, и, раз это ему плёвое дело - 6 раз отфулсканить uix_person_channel_p2 ,
значит, надо либо его просто грохнуть, и смотреть, что он будет делать дальше.
Либо добавить строчек.

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

PS
По ходу пьесы почитал то да сё вокруг вопроса "postgress и движение материи".
Премного подивился. Кажется, за него кто-то всерьёз и плотно внезапно взялся, и так уж и давно.
Я с разбегу не вынес суждения, кто точно и как это варит. В главных спонсорах Microsoft в лице CitusData и Fujitsu.
Просто в спонсорах Amazon, IBM, Google и Yandex.
Так, или иначе, но интенсивность бурления и развития вокруг предмета за последнюю пятилетку вполне произвела впечатление.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079754
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
booby
mayton
На какой-же синтетике вы гоняете ваши бенчмарки. На табличках из 1-й колонки?

А бедняга автор затащит это себе где 1 datarow равен блоку

Так пузами только на синтетике и меряются.
А еще обязательно на прогретых данных, и в одно рыло, без конкуренции за диски и процессор.

2Maxim Boguk
сдаётся, что маловато данных для конкретного окружения.
Индекс коротковат, и, раз это ему плёвое дело - 6 раз отфулсканить uix_person_channel_p2 ,
значит, надо либо его просто грохнуть, и смотреть, что он будет делать дальше.
Либо добавить строчек.


Таки на прогретых данных разницы не будет... там же не full index scan а index only scan который только нужные строчки в индексе проходит.
Там full скана индекса ни в одной ветке не происходит. А тогда просто вопрос в том чтобы индекс в shared buffers лежал.


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40079766
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,
когда индекс в shared buffers - это и есть "прогретые данные".
почему, кстати, вы не показывете, в сравнении, результаты от intersect?

дело-то вот в чём: вы "топите" за очевидно нереляционное решение, с захардкоженными поисковыми параметрами.
Это весьма условно и приблизительно может быть вообще отнесено к категории "sql" и "работа с базой данных".
По сути, вы говорите, что частный случай - самый лучший, всегда исходите из частного случая.

Вот если бы вы показали, как какой-то вариант рекурсивного, например, запроса наотмашь бьёт
все остальные варианты работы с реляционной таблицей требований, это был бы совсем другой разговор.

Вместо этого вы советуете таблиц вообще не использовать, потому что субд с таблицами работает плохо,
т.е. - почти не умеет, а с захардкоженными значенями умеет работать очень хорошо...
Это прямо зашибись какое-то, очевидно, что самый лучший профессиональный совет.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083340
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Boguk,

я применил запрос по вашему совету

сам запрос выглядит так

Код: plsql
1.
2.
3.
4.
5.
6.
7.
select p.*
from respondent p
where exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'EMAIL')
  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'SMS')
  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'PUSH')
  and p.space_id = 1
  and p.deleted_at is null



всего в таблице 2 млн респондентов
индексы из вашего примера
1.уникальный на respondent_id channel_type
2.обычый индекс на channel_type

аналитика по запросу

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
Gather  (cost=74938.89..354961.35 rows=334684 width=276) (actual time=374.626..3153.443 rows=333335 loops=1)
  Workers Planned: 2
  Workers Launched: 2
  ->  Nested Loop  (cost=73938.89..320492.95 rows=139452 width=276) (actual time=325.696..2941.918 rows=111112 loops=3)
        ->  Nested Loop  (cost=73938.47..209098.75 rows=163608 width=24) (actual time=324.900..1410.851 rows=111112 loops=3)
              ->  Parallel Hash Join  (cost=73938.04..131767.11 rows=151040 width=16) (actual time=324.100..509.668 rows=111112 loops=3)
                    Hash Cond: (rc_1.respondent_id = rc_2.respondent_id)
                    ->  Parallel Bitmap Heap Scan on respondent_channel rc_1  (cost=11056.62..63470.11 rows=413559 width=8) (actual time=35.420..116.657 rows=333335 loops=3)
                          Recheck Cond: (channel_type = 'SMS'::text)
                          Heap Blocks: exact=3141
                          ->  Bitmap Index Scan on respondent_channel_channel_type  (cost=0.00..10808.49 rows=992541 width=0) (actual time=33.630..33.630 rows=1000005 loops=1)
                                Index Cond: (channel_type = 'SMS'::text)
                    ->  Parallel Hash  (cost=58271.09..58271.09 rows=280986 width=8) (actual time=126.210..126.211 rows=222223 loops=3)
                          Buckets: 131072  Batches: 16  Memory Usage: 2688kB
                          ->  Parallel Bitmap Heap Scan on respondent_channel rc_2  (cost=7514.77..58271.09 rows=280986 width=8) (actual time=8.623..70.018 rows=222223 loops=3)
                                Recheck Cond: (channel_type = 'PUSH'::text)
                                Heap Blocks: exact=3526
                                ->  Bitmap Index Scan on respondent_channel_channel_type  (cost=0.00..7346.18 rows=674366 width=0) (actual time=24.642..24.642 rows=666670 loops=1)
                                      Index Cond: (channel_type = 'PUSH'::text)
              ->  Index Only Scan using respondent_id_channel on respondent_channel rc  (cost=0.43..0.51 rows=1 width=8) (actual time=0.008..0.008 rows=1 loops=333335)
                    Index Cond: ((respondent_id = rc_1.respondent_id) AND (channel_type = 'EMAIL'::text))
                    Heap Fetches: 0
        ->  Index Scan using respondent_pkey on respondent p  (cost=0.43..0.68 rows=1 width=276) (actual time=0.013..0.013 rows=1 loops=333335)
              Index Cond: (id = rc.respondent_id)
              Filter: ((deleted_at IS NULL) AND (space_id = 1))
Planning Time: 0.937 ms
Execution Time: 3170.429 ms



вопрос почему так долго ? может не хватает каких то индексов?
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083344
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
O_79_O,

Выглядит как более менее нормальная скорость на том количестве и распределении данных что у вас есть и при отсутствии (о чём я писал) селективного channel_type.

Я бы рекомендовал включить track_io_timing в конфиге базы и сделать
explain (analyze, costs, buffers, timing) запроса несколько раз
может оно просто с дисков много читает первый раз и поэтому медленно.

PS: а какие у вас настройки базы в части random_page_cost/seq_page_cost/shared_buffers?

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083350
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Boguk,
насчет настроек сказать не могу - я не админ базы этой

смотрите у меня вопрос такой

вот этот запрос с лимитом

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select p.*
from respondent p
where exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'EMAIL')
  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'SMS')
  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'PUSH')
  and p.space_id = 1
  and p.deleted_at is null
offset 0
limit 12;



запрос выполняется за 100 мс

теперь я тоже самое делаю но через хибернейтовский entityManager
и получаю в лучшем случае 3 секунды от начала запроса через постман до получения джейсона

по логам видно что хибер отправляет ровно тот же запрос с ровно теми же параметрами
куда уходит 3 секунды - неужели на мапинг 12 простеньких объектов

по времени как запрос без лимита из консоли- очень странное поведение
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083364
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
O_79_O,

1)"вот этот запрос с лимитом" - это другой запрос с другим планом
который надо смотреть
и кстати оптимизация запроса с limit совсем не тоже самое что оптимизация запроса на все строки.

2)через JDBC там вообще могут быть варианты как именно он запрос отправляет
и без доступа к логам базы - на это ответить нельзя
надо включать лог запросов в базе и смотреть ЧТО именно пришло от приложения
с какими параметрами
и сколько запрос выполнялся.

PS: попробуйте в запрос добавить order by p.id OFFSET 0 LIMIT 12 и руками и для JDBC
может поможет выбрать план подходящий под вас.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083366
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Boguk
O_79_O,

1)"вот этот запрос с лимитом" - это другой запрос с другим планом
который надо смотреть
и кстати оптимизация запроса с limit совсем не тоже самое что оптимизация запроса на все строки.

2)через JDBC там вообще могут быть варианты как именно он запрос отправляет
и без доступа к логам базы - на это ответить нельзя
надо включать лог запросов в базе и смотреть ЧТО именно пришло от приложения
с какими параметрами
и сколько запрос выполнялся.

PS: попробуйте в запрос добавить order by p.id OFFSET 0 LIMIT 12 и руками и для JDBC
может поможет выбрать план подходящий под вас.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru


1 по первому пункту - понял,но ведь работает все идеально - 90-100 мс меня вполне устраивают эти цифры
2.по второму вопросу сейчас попробую сделать логи
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083368
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
без добавления p.id
запрос
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
explain analyze
select p.*
from respondent p
where exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'EMAIL')
  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'SMS')
  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'PUSH')
  and p.space_id = 1
  and p.deleted_at is null
offset 0
limit 12;


аналитика
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
Limit  (cost=1.72..22.83 rows=12 width=276) (actual time=0.072..0.123 rows=12 loops=1)
  ->  Nested Loop  (cost=1.72..588717.46 rows=334591 width=276) (actual time=0.071..0.120 rows=12 loops=1)
        ->  Merge Join  (cost=1.29..321388.23 rows=392622 width=24) (actual time=0.054..0.076 rows=12 loops=1)
              Merge Cond: (rc_1.respondent_id = rc.respondent_id)
              ->  Merge Join  (cost=0.86..202524.14 rows=362461 width=16) (actual time=0.039..0.050 rows=12 loops=1)
                    Merge Cond: (rc_1.respondent_id = rc_2.respondent_id)
                    ->  Index Only Scan using respondent_id_channel on respondent_channel rc_1  (cost=0.43..98957.06 rows=992449 width=8) (actual time=0.021..0.025 rows=36 loops=1)
                          Index Cond: (channel_type = 'SMS'::text)
                          Heap Fetches: 0
                    ->  Index Only Scan using respondent_id_channel on respondent_channel rc_2  (cost=0.43..95775.60 rows=674303 width=8) (actual time=0.013..0.016 rows=24 loops=1)
                          Index Cond: (channel_type = 'PUSH'::text)
                          Heap Fetches: 0
              ->  Index Only Scan using respondent_id_channel on respondent_channel rc  (cost=0.43..109031.89 rows=1999932 width=8) (actual time=0.013..0.017 rows=71 loops=1)
                    Index Cond: (channel_type = 'EMAIL'::text)
                    Heap Fetches: 0
        ->  Index Scan using respondent_pkey on respondent p  (cost=0.43..0.68 rows=1 width=276) (actual time=0.003..0.003 rows=1 loops=12)
              Index Cond: (id = rc.respondent_id)
              Filter: ((deleted_at IS NULL) AND (space_id = 1))
Planning Time: 1.218 ms
Execution Time: 0.174 ms



с сортировкой p.id

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
Limit  (cost=1.72..22.83 rows=12 width=276) (actual time=0.058..0.097 rows=12 loops=1)
  ->  Nested Loop  (cost=1.72..588717.46 rows=334591 width=276) (actual time=0.058..0.095 rows=12 loops=1)
        ->  Merge Join  (cost=1.29..321388.23 rows=392622 width=24) (actual time=0.047..0.063 rows=12 loops=1)
              Merge Cond: (rc_1.respondent_id = rc.respondent_id)
              ->  Merge Join  (cost=0.86..202524.14 rows=362461 width=16) (actual time=0.035..0.042 rows=12 loops=1)
                    Merge Cond: (rc_1.respondent_id = rc_2.respondent_id)
                    ->  Index Only Scan using respondent_id_channel on respondent_channel rc_1  (cost=0.43..98957.06 rows=992449 width=8) (actual time=0.021..0.024 rows=36 loops=1)
                          Index Cond: (channel_type = 'SMS'::text)
                          Heap Fetches: 0
                    ->  Index Only Scan using respondent_id_channel on respondent_channel rc_2  (cost=0.43..95775.60 rows=674303 width=8) (actual time=0.010..0.012 rows=24 loops=1)
                          Index Cond: (channel_type = 'PUSH'::text)
                          Heap Fetches: 0
              ->  Index Only Scan using respondent_id_channel on respondent_channel rc  (cost=0.43..109031.89 rows=1999932 width=8) (actual time=0.011..0.016 rows=71 loops=1)
                    Index Cond: (channel_type = 'EMAIL'::text)
                    Heap Fetches: 0
        ->  Index Scan using respondent_pkey on respondent p  (cost=0.43..0.68 rows=1 width=276) (actual time=0.002..0.002 rows=1 loops=12)
              Index Cond: (id = rc.respondent_id)
              Filter: ((deleted_at IS NULL) AND (space_id = 1))
Planning Time: 1.103 ms
Execution Time: 0.145 ms
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083373
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
скорей всего проблема в том что Хибернейт не умеет полноценно работать с limit
ибо сейчас я вижу что время ответа как раз похоже тому - что как если бы я сделал аналитику запроса этого без лимита - как раз жи 3 с лишним секунды

мне видится что хибер выгребает из бд все - а потом отдает тебе кусок по лимиту

например полнотектовый поиск из консоли дает 0.12 секунд а через приложение уже 500 мс - почти в 4000 раз дольше
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083375
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083378
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость

так и делаю ,никаких результатов - тоже самое если просто руками прописываю лимит в sql стетмейнт
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083380
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ты не разобрался как я вижу на какую фазу SQL тратится время. Я напомню.

1) Фаза execution . Это работа числто в пространстве процесса PG (сортировки группировки и джойны). Данные при этом в сокет JDBC еще не выдаются.
2) Фаза fetch . Здесь PG начинает выдавать строки row-by-row по JBDC линку. И здесь работает Hiber-mapping и вообще
вся твоя бизнес-логика.

Замеряй время (в милисекундаз) в 3х точках и вычисли дельту между ними и ты получишь эти два интервала.

Как только мы узнаем где проблема (какой интервал длиннее) - так мы и будем фиксить.

Без этой информации у нас нет стратегии. Неясно что мы ищем и где.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083385
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mayton
Ты не разобрался как я вижу на какую фазу SQL тратится время. Я напомню.

1) Фаза execution . Это работа числто в пространстве процесса PG (сортировки группировки и джойны). Данные при этом в сокет JDBC еще не выдаются.
2) Фаза fetch . Здесь PG начинает выдавать строки row-by-row по JBDC линку. И здесь работает Hiber-mapping и вообще
вся твоя бизнес-логика.

Замеряй время (в милисекундаз) в 3х точках и вычисли дельту между ними и ты получишь эти два интервала.

Как только мы узнаем где проблема (какой интервал длиннее) - так мы и будем фиксить.

Без этой информации у нас нет стратегии. Неясно что мы ищем и где.

майтон можешь не засорять тему ? спасибо заранее
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083389
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
O_79_O

так и делаю ,никаких результатов - тоже самое если просто руками прописываю лимит в sql стетмейнт


Я вам уже написал - без доступов к логам базы (и включению log_min_duration_statement) для понимания что именно от приложения в базу приходит
и с какими параметрами - на эти вопросы ответить нельзя.
Просите логи базы с параметрами и временем выполения или сами смотрите.
Или тестовую базу у себя поднимайте с тестовыми данными и гоняйте на ней с включеными логами.
Без этой информации нет смысла в дальнейшей дискуссии.

Я не помню проблем с jdbc и limit у postgresql в тех местах где он используется.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083391
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Boguk


Я вам уже написал - без доступов к логам базы (и включению log_min_duration_statement) для понимания что именно от приложения в базу приходит
и с какими параметрами - на эти вопросы ответить нельзя.
Просите логи базы с параметрами и временем выполения или сами смотрите.
Или тестовую базу у себя поднимайте с тестовыми данными и гоняйте на ней с включеными логами.
Без этой информации нет смысла в дальнейшей дискуссии.


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru


база у меня поднята локально,но я понятия не имею как там смотреть логи ( я на винде работаю) и как включать параметры ,а которых вы говорите
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083403
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Boguk,
таки домучал логи вот что из приложения прилетает
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
2021-07-12 16:55:34.982 MSK [7888] LOG:  duration: 0.817 ms
2021-07-12 16:55:34.987 MSK [7888] LOG:  duration: 0.031 ms  parse <unnamed>: BEGIN
2021-07-12 16:55:34.988 MSK [7888] LOG:  duration: 0.010 ms  bind <unnamed>: BEGIN
2021-07-12 16:55:34.989 MSK [21780] LOG:  duration: 0.045 ms  parse <unnamed>: 
2021-07-12 16:55:34.989 MSK [7888] LOG:  execute <unnamed>: BEGIN
2021-07-12 16:55:34.990 MSK [21780] LOG:  duration: 0.006 ms  bind <unnamed>: 
2021-07-12 16:55:34.990 MSK [7888] LOG:  duration: 1.114 ms
2021-07-12 16:55:34.993 MSK [21780] LOG:  duration: 0.037 ms  parse <unnamed>: BEGIN
2021-07-12 16:55:34.994 MSK [21780] LOG:  duration: 0.017 ms  bind <unnamed>: BEGIN
2021-07-12 16:55:34.994 MSK [7888] LOG:  duration: 2.932 ms  parse <unnamed>: select p.* from respondent p where exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'EMAIL') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'SMS') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'PUSH') and p.space_id = 1 and p.deleted_at is null limit $1
2021-07-12 16:55:34.995 MSK [21780] LOG:  execute <unnamed>: BEGIN
2021-07-12 16:55:34.996 MSK [21780] LOG:  duration: 1.082 ms
2021-07-12 16:55:35.001 MSK [21780] LOG:  duration: 4.756 ms  parse <unnamed>: update "user" set last_request_at = $1 where id = $2
2021-07-12 16:55:35.004 MSK [7888] LOG:  duration: 9.240 ms  bind <unnamed>/C_2: select p.* from respondent p where exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'EMAIL') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'SMS') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'PUSH') and p.space_id = 1 and p.deleted_at is null limit $1
2021-07-12 16:55:35.004 MSK [7888] DETAIL:  parameters: $1 = '12'
2021-07-12 16:55:35.006 MSK [7888] LOG:  execute <unnamed>/C_2: select p.* from respondent p where exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'EMAIL') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'SMS') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'PUSH') and p.space_id = 1 and p.deleted_at is null limit $1
2021-07-12 16:55:35.006 MSK [7888] DETAIL:  parameters: $1 = '12'
2021-07-12 16:55:35.006 MSK [21780] LOG:  duration: 4.016 ms  bind <unnamed>: update "user" set last_request_at = $1 where id = $2
2021-07-12 16:55:35.006 MSK [21780] DETAIL:  parameters: $1 = '2021-07-12 16:55:34.984744+03', $2 = '1'
2021-07-12 16:55:35.007 MSK [7888] LOG:  duration: 1.440 ms
2021-07-12 16:55:35.007 MSK [21780] LOG:  execute <unnamed>: update "user" set last_request_at = $1 where id = $2
2021-07-12 16:55:35.007 MSK [21780] DETAIL:  parameters: $1 = '2021-07-12 16:55:34.984744+03', $2 = '1'
2021-07-12 16:55:35.014 MSK [21780] LOG:  duration: 7.272 ms
2021-07-12 16:55:35.015 MSK [7888] LOG:  duration: 0.326 ms  parse <unnamed>: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.015 MSK [21780] LOG:  duration: 0.034 ms  parse S_1: COMMIT
2021-07-12 16:55:35.016 MSK [21780] LOG:  duration: 0.012 ms  bind S_1: COMMIT
2021-07-12 16:55:35.017 MSK [21780] LOG:  execute S_1: COMMIT
2021-07-12 16:55:35.019 MSK [21780] LOG:  duration: 2.060 ms
2021-07-12 16:55:35.019 MSK [7888] LOG:  duration: 2.786 ms  bind <unnamed>/C_3: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.019 MSK [7888] DETAIL:  parameters: $1 = '2148078'
2021-07-12 16:55:35.020 MSK [7888] LOG:  execute <unnamed>/C_3: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.020 MSK [7888] DETAIL:  parameters: $1 = '2148078'
2021-07-12 16:55:35.021 MSK [7888] LOG:  duration: 1.552 ms
2021-07-12 16:55:35.022 MSK [7888] LOG:  duration: 0.078 ms  parse <unnamed>: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.024 MSK [7888] LOG:  duration: 0.231 ms  bind <unnamed>/C_4: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.024 MSK [7888] DETAIL:  parameters: $1 = '2148072'
2021-07-12 16:55:35.025 MSK [7888] LOG:  execute <unnamed>/C_4: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.025 MSK [7888] DETAIL:  parameters: $1 = '2148072'
2021-07-12 16:55:35.025 MSK [7888] LOG:  duration: 1.151 ms
2021-07-12 16:55:35.027 MSK [7888] LOG:  duration: 0.124 ms  parse <unnamed>: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.029 MSK [7888] LOG:  duration: 0.265 ms  bind <unnamed>/C_5: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.029 MSK [7888] DETAIL:  parameters: $1 = '2148066'
2021-07-12 16:55:35.030 MSK [7888] LOG:  execute <unnamed>/C_5: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.030 MSK [7888] DETAIL:  parameters: $1 = '2148066'
2021-07-12 16:55:35.031 MSK [7888] LOG:  duration: 1.728 ms
2021-07-12 16:55:35.033 MSK [7888] LOG:  duration: 0.079 ms  parse <unnamed>: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.034 MSK [7888] LOG:  duration: 0.214 ms  bind <unnamed>/C_6: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.034 MSK [7888] DETAIL:  parameters: $1 = '2148060'
2021-07-12 16:55:35.036 MSK [7888] LOG:  execute <unnamed>/C_6: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.036 MSK [7888] DETAIL:  parameters: $1 = '2148060'
2021-07-12 16:55:35.037 MSK [7888] LOG:  duration: 1.532 ms
2021-07-12 16:55:35.038 MSK [7888] LOG:  duration: 0.095 ms  parse S_7: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.039 MSK [7888] LOG:  duration: 0.180 ms  bind S_7/C_8: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.039 MSK [7888] DETAIL:  parameters: $1 = '2148054'
2021-07-12 16:55:35.040 MSK [7888] LOG:  execute S_7/C_8: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.040 MSK [7888] DETAIL:  parameters: $1 = '2148054'
2021-07-12 16:55:35.041 MSK [7888] LOG:  duration: 1.193 ms
2021-07-12 16:55:35.043 MSK [7888] LOG:  duration: 0.229 ms  bind S_7/C_9: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.043 MSK [7888] DETAIL:  parameters: $1 = '2148048'
2021-07-12 16:55:35.045 MSK [7888] LOG:  execute S_7/C_9: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.045 MSK [7888] DETAIL:  parameters: $1 = '2148048'
2021-07-12 16:55:35.046 MSK [7888] LOG:  duration: 1.825 ms
2021-07-12 16:55:35.048 MSK [7888] LOG:  duration: 0.178 ms  bind S_7/C_10: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.048 MSK [7888] DETAIL:  parameters: $1 = '2148042'
2021-07-12 16:55:35.050 MSK [7888] LOG:  execute S_7/C_10: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.050 MSK [7888] DETAIL:  parameters: $1 = '2148042'
2021-07-12 16:55:35.050 MSK [7888] LOG:  duration: 1.193 ms
2021-07-12 16:55:35.052 MSK [7888] LOG:  duration: 0.195 ms  bind S_7/C_11: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.052 MSK [7888] DETAIL:  parameters: $1 = '2148036'
2021-07-12 16:55:35.054 MSK [7888] LOG:  execute S_7/C_11: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.054 MSK [7888] DETAIL:  parameters: $1 = '2148036'
2021-07-12 16:55:35.054 MSK [7888] LOG:  duration: 1.503 ms
2021-07-12 16:55:35.056 MSK [7888] LOG:  duration: 0.172 ms  bind S_7/C_12: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.056 MSK [7888] DETAIL:  parameters: $1 = '2148030'
2021-07-12 16:55:35.058 MSK [7888] LOG:  execute S_7/C_12: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.058 MSK [7888] DETAIL:  parameters: $1 = '2148030'
2021-07-12 16:55:35.059 MSK [7888] LOG:  duration: 1.218 ms
2021-07-12 16:55:35.062 MSK [7888] LOG:  duration: 0.222 ms  bind S_7/C_13: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.062 MSK [7888] DETAIL:  parameters: $1 = '2148024'
2021-07-12 16:55:35.064 MSK [7888] LOG:  execute S_7/C_13: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.064 MSK [7888] DETAIL:  parameters: $1 = '2148024'
2021-07-12 16:55:35.064 MSK [7888] LOG:  duration: 1.411 ms
2021-07-12 16:55:35.066 MSK [7888] LOG:  duration: 0.039 ms  bind S_7/C_14: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.066 MSK [7888] DETAIL:  parameters: $1 = '2148018'
2021-07-12 16:55:35.067 MSK [7888] LOG:  execute S_7/C_14: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.067 MSK [7888] DETAIL:  parameters: $1 = '2148018'
2021-07-12 16:55:35.068 MSK [7888] LOG:  duration: 1.224 ms
2021-07-12 16:55:35.070 MSK [7888] LOG:  duration: 0.070 ms  bind S_7/C_15: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.070 MSK [7888] DETAIL:  parameters: $1 = '2148012'
2021-07-12 16:55:35.071 MSK [7888] LOG:  execute S_7/C_15: select respondent0_.respondent_id as responde3_80_0_, respondent0_.respondent_group_id as responde2_80_0_, respondent1_.id as id1_79_1_, respondent1_.created_at as created_2_79_1_, respondent1_.deleted_at as deleted_3_79_1_, respondent1_.updated_at as updated_4_79_1_, respondent1_.group_name as group_na5_79_1_, respondent1_.space_id as space_id6_79_1_ from respondent_respondent_group respondent0_ inner join respondent_group respondent1_ on respondent0_.respondent_group_id=respondent1_.id and ( respondent1_.deleted_at is null) where respondent0_.respondent_id=$1
2021-07-12 16:55:35.071 MSK [7888] DETAIL:  parameters: $1 = '2148012'
2021-07-12 16:55:35.073 MSK [7888] LOG:  duration: 2.217 ms
2021-07-12 16:55:35.080 MSK [7888] LOG:  duration: 2.714 ms  parse <unnamed>: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.087 MSK [7888] LOG:  duration: 6.634 ms  bind <unnamed>/C_16: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.087 MSK [7888] DETAIL:  parameters: $1 = '2148012'
2021-07-12 16:55:35.088 MSK [7888] LOG:  execute <unnamed>/C_16: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.088 MSK [7888] DETAIL:  parameters: $1 = '2148012'
2021-07-12 16:55:35.089 MSK [7888] LOG:  duration: 1.166 ms
2021-07-12 16:55:35.090 MSK [7888] LOG:  duration: 0.065 ms  parse <unnamed>: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.091 MSK [7888] LOG:  duration: 0.144 ms  bind <unnamed>/C_17: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.091 MSK [7888] DETAIL:  parameters: $1 = '2148012'
2021-07-12 16:55:35.092 MSK [7888] LOG:  execute <unnamed>/C_17: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.092 MSK [7888] DETAIL:  parameters: $1 = '2148012'
2021-07-12 16:55:35.094 MSK [7888] LOG:  duration: 1.809 ms
2021-07-12 16:55:35.101 MSK [7888] LOG:  duration: 0.089 ms  parse <unnamed>: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.102 MSK [7888] LOG:  duration: 0.289 ms  bind <unnamed>/C_18: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.102 MSK [7888] DETAIL:  parameters: $1 = '2148018'
2021-07-12 16:55:35.103 MSK [7888] LOG:  execute <unnamed>/C_18: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.103 MSK [7888] DETAIL:  parameters: $1 = '2148018'
2021-07-12 16:55:35.104 MSK [7888] LOG:  duration: 1.431 ms
2021-07-12 16:55:35.107 MSK [7888] LOG:  duration: 0.096 ms  parse <unnamed>: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.108 MSK [7888] LOG:  duration: 0.157 ms  bind <unnamed>/C_19: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.108 MSK [7888] DETAIL:  parameters: $1 = '2148018'
2021-07-12 16:55:35.109 MSK [7888] LOG:  execute <unnamed>/C_19: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.109 MSK [7888] DETAIL:  parameters: $1 = '2148018'
2021-07-12 16:55:35.110 MSK [7888] LOG:  duration: 1.847 ms
2021-07-12 16:55:35.116 MSK [7888] LOG:  duration: 0.115 ms  parse <unnamed>: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.117 MSK [7888] LOG:  duration: 0.263 ms  bind <unnamed>/C_20: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.117 MSK [7888] DETAIL:  parameters: $1 = '2148024'
2021-07-12 16:55:35.118 MSK [7888] LOG:  execute <unnamed>/C_20: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.118 MSK [7888] DETAIL:  parameters: $1 = '2148024'
2021-07-12 16:55:35.119 MSK [7888] LOG:  duration: 1.150 ms
2021-07-12 16:55:35.121 MSK [7888] LOG:  duration: 0.062 ms  parse <unnamed>: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.122 MSK [7888] LOG:  duration: 0.160 ms  bind <unnamed>/C_21: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.122 MSK [7888] DETAIL:  parameters: $1 = '2148024'
2021-07-12 16:55:35.123 MSK [7888] LOG:  execute <unnamed>/C_21: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.123 MSK [7888] DETAIL:  parameters: $1 = '2148024'
2021-07-12 16:55:35.124 MSK [7888] LOG:  duration: 1.167 ms
2021-07-12 16:55:35.136 MSK [7888] LOG:  duration: 0.160 ms  parse <unnamed>: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.137 MSK [7888] LOG:  duration: 0.241 ms  bind <unnamed>/C_22: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.137 MSK [7888] DETAIL:  parameters: $1 = '2148030'
2021-07-12 16:55:35.138 MSK [7888] LOG:  execute <unnamed>/C_22: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.138 MSK [7888] DETAIL:  parameters: $1 = '2148030'
2021-07-12 16:55:35.139 MSK [7888] LOG:  duration: 1.166 ms
2021-07-12 16:55:35.141 MSK [7888] LOG:  duration: 0.132 ms  parse <unnamed>: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.142 MSK [7888] LOG:  duration: 0.109 ms  bind <unnamed>/C_23: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.142 MSK [7888] DETAIL:  parameters: $1 = '2148030'
2021-07-12 16:55:35.144 MSK [7888] LOG:  execute <unnamed>/C_23: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.144 MSK [7888] DETAIL:  parameters: $1 = '2148030'
2021-07-12 16:55:35.145 MSK [7888] LOG:  duration: 1.704 ms
2021-07-12 16:55:35.152 MSK [7888] LOG:  duration: 0.124 ms  parse S_24: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.153 MSK [7888] LOG:  duration: 0.238 ms  bind S_24/C_25: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.153 MSK [7888] DETAIL:  parameters: $1 = '2148036'
2021-07-12 16:55:35.154 MSK [7888] LOG:  execute S_24/C_25: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.154 MSK [7888] DETAIL:  parameters: $1 = '2148036'
2021-07-12 16:55:35.155 MSK [7888] LOG:  duration: 1.216 ms
2021-07-12 16:55:35.156 MSK [7888] LOG:  duration: 0.085 ms  parse S_26: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.157 MSK [7888] LOG:  duration: 0.238 ms  bind S_26/C_27: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.157 MSK [7888] DETAIL:  parameters: $1 = '2148036'
2021-07-12 16:55:35.158 MSK [7888] LOG:  execute S_26/C_27: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.158 MSK [7888] DETAIL:  parameters: $1 = '2148036'
2021-07-12 16:55:35.159 MSK [7888] LOG:  duration: 1.271 ms
2021-07-12 16:55:35.164 MSK [7888] LOG:  duration: 0.191 ms  bind S_24/C_28: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.164 MSK [7888] DETAIL:  parameters: $1 = '2148042'
2021-07-12 16:55:35.165 MSK [7888] LOG:  execute S_24/C_28: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.165 MSK [7888] DETAIL:  parameters: $1 = '2148042'
2021-07-12 16:55:35.166 MSK [7888] LOG:  duration: 1.082 ms
2021-07-12 16:55:35.167 MSK [7888] LOG:  duration: 0.092 ms  bind S_26/C_29: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.167 MSK [7888] DETAIL:  parameters: $1 = '2148042'
2021-07-12 16:55:35.168 MSK [7888] LOG:  execute S_26/C_29: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.168 MSK [7888] DETAIL:  parameters: $1 = '2148042'
2021-07-12 16:55:35.169 MSK [7888] LOG:  duration: 1.106 ms
2021-07-12 16:55:35.172 MSK [7888] LOG:  duration: 0.213 ms  bind S_24/C_30: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.172 MSK [7888] DETAIL:  parameters: $1 = '2148048'
2021-07-12 16:55:35.174 MSK [7888] LOG:  execute S_24/C_30: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.174 MSK [7888] DETAIL:  parameters: $1 = '2148048'
2021-07-12 16:55:35.175 MSK [7888] LOG:  duration: 1.988 ms
2021-07-12 16:55:35.178 MSK [7888] LOG:  duration: 0.155 ms  bind S_26/C_31: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.178 MSK [7888] DETAIL:  parameters: $1 = '2148048'
2021-07-12 16:55:35.180 MSK [7888] LOG:  execute S_26/C_31: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.180 MSK [7888] DETAIL:  parameters: $1 = '2148048'
2021-07-12 16:55:35.180 MSK [7888] LOG:  duration: 1.432 ms
2021-07-12 16:55:35.184 MSK [7888] LOG:  duration: 0.189 ms  bind S_24/C_32: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.184 MSK [7888] DETAIL:  parameters: $1 = '2148054'
2021-07-12 16:55:35.185 MSK [7888] LOG:  execute S_24/C_32: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.185 MSK [7888] DETAIL:  parameters: $1 = '2148054'
2021-07-12 16:55:35.186 MSK [7888] LOG:  duration: 1.084 ms
2021-07-12 16:55:35.187 MSK [7888] LOG:  duration: 0.122 ms  bind S_26/C_33: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.187 MSK [7888] DETAIL:  parameters: $1 = '2148054'
2021-07-12 16:55:35.189 MSK [7888] LOG:  execute S_26/C_33: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.189 MSK [7888] DETAIL:  parameters: $1 = '2148054'
2021-07-12 16:55:35.189 MSK [7888] LOG:  duration: 1.198 ms
2021-07-12 16:55:35.194 MSK [7888] LOG:  duration: 0.275 ms  bind S_24/C_34: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.194 MSK [7888] DETAIL:  parameters: $1 = '2148060'
2021-07-12 16:55:35.195 MSK [7888] LOG:  execute S_24/C_34: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.195 MSK [7888] DETAIL:  parameters: $1 = '2148060'
2021-07-12 16:55:35.196 MSK [7888] LOG:  duration: 1.380 ms
2021-07-12 16:55:35.198 MSK [7888] LOG:  duration: 0.101 ms  bind S_26/C_35: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.198 MSK [7888] DETAIL:  parameters: $1 = '2148060'
2021-07-12 16:55:35.199 MSK [7888] LOG:  execute S_26/C_35: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.199 MSK [7888] DETAIL:  parameters: $1 = '2148060'
2021-07-12 16:55:35.200 MSK [7888] LOG:  duration: 1.194 ms
2021-07-12 16:55:35.204 MSK [7888] LOG:  duration: 0.206 ms  bind S_24/C_36: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.204 MSK [7888] DETAIL:  parameters: $1 = '2148066'
2021-07-12 16:55:35.205 MSK [7888] LOG:  execute S_24/C_36: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.205 MSK [7888] DETAIL:  parameters: $1 = '2148066'
2021-07-12 16:55:35.206 MSK [7888] LOG:  duration: 1.693 ms
2021-07-12 16:55:35.208 MSK [7888] LOG:  duration: 0.122 ms  bind S_26/C_37: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.208 MSK [7888] DETAIL:  parameters: $1 = '2148066'
2021-07-12 16:55:35.210 MSK [7888] LOG:  execute S_26/C_37: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.210 MSK [7888] DETAIL:  parameters: $1 = '2148066'
2021-07-12 16:55:35.211 MSK [7888] LOG:  duration: 1.721 ms
2021-07-12 16:55:35.215 MSK [7888] LOG:  duration: 0.054 ms  bind S_24/C_38: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.215 MSK [7888] DETAIL:  parameters: $1 = '2148072'
2021-07-12 16:55:35.216 MSK [7888] LOG:  execute S_24/C_38: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.216 MSK [7888] DETAIL:  parameters: $1 = '2148072'
2021-07-12 16:55:35.217 MSK [7888] LOG:  duration: 1.270 ms
2021-07-12 16:55:35.219 MSK [7888] LOG:  duration: 0.027 ms  bind S_26/C_39: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.219 MSK [7888] DETAIL:  parameters: $1 = '2148072'
2021-07-12 16:55:35.220 MSK [7888] LOG:  execute S_26/C_39: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.220 MSK [7888] DETAIL:  parameters: $1 = '2148072'
2021-07-12 16:55:35.221 MSK [7888] LOG:  duration: 1.222 ms
2021-07-12 16:55:35.224 MSK [7888] LOG:  duration: 0.031 ms  bind S_24/C_40: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.224 MSK [7888] DETAIL:  parameters: $1 = '2148078'
2021-07-12 16:55:35.225 MSK [7888] LOG:  execute S_24/C_40: select ap.id as answer_poll_id,p.name as poll_name,ap.started_at as start_date,extract(epoch from (ap.finished_at - ap.started_at)) as duration,ap.comment from oprosso.public.answer_poll ap join poll p on ap.poll_id = p.id where ap.finished_at is not null and ap.debug is false and ap.deleted_at is null and ap.respondent_id = $1
2021-07-12 16:55:35.225 MSK [7888] DETAIL:  parameters: $1 = '2148078'
2021-07-12 16:55:35.226 MSK [7888] LOG:  duration: 1.413 ms
2021-07-12 16:55:35.229 MSK [7888] LOG:  duration: 0.031 ms  bind S_26/C_41: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.229 MSK [7888] DETAIL:  parameters: $1 = '2148078'
2021-07-12 16:55:35.230 MSK [7888] LOG:  execute S_26/C_41: select respondent0_.respondent_id as responde8_78_0_, respondent0_.id as id1_78_0_, respondent0_.id as id1_78_1_, respondent0_.created_at as created_2_78_1_, respondent0_.deleted_at as deleted_3_78_1_, respondent0_.updated_at as updated_4_78_1_, respondent0_.channel_name as channel_5_78_1_, respondent0_.channel_state as channel_6_78_1_, respondent0_.channel_type as channel_7_78_1_, respondent0_.respondent_id as responde8_78_1_ from respondent_channel respondent0_ where ( respondent0_.deleted_at is null) and respondent0_.respondent_id=$1
2021-07-12 16:55:35.230 MSK [7888] DETAIL:  parameters: $1 = '2148078'
2021-07-12 16:55:35.231 MSK [7888] LOG:  duration: 1.365 ms
2021-07-12 16:55:35.236 MSK [7888] LOG:  duration: 1.363 ms  parse <unnamed>: select count(*) from respondent p where exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'EMAIL') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'SMS') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'PUSH') and p.space_id = 1 and p.deleted_at is null
2021-07-12 16:55:35.237 MSK [7888] LOG:  duration: 1.211 ms  bind <unnamed>/C_42: select count(*) from respondent p where exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'EMAIL') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'SMS') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'PUSH') and p.space_id = 1 and p.deleted_at is null
2021-07-12 16:55:35.238 MSK [7888] LOG:  execute <unnamed>/C_42: select count(*) from respondent p where exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'EMAIL') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'SMS') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'PUSH') and p.space_id = 1 and p.deleted_at is null
2021-07-12 16:55:41.657 MSK [7888] LOG:  duration: 6419.398 ms
2021-07-12 16:55:41.660 MSK [7888] LOG:  duration: 0.007 ms  bind S_1: COMMIT
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083406
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
а вот это образуется в логах если сделать запрос из консоли

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
2021-07-12 17:03:21.599 MSK [22188] DETAIL:  parameters: $1 = '1003'
2021-07-12 17:03:21.601 MSK [22188] LOG:  execute <unnamed>: SELECT e.typdelim FROM pg_catalog.pg_type t, pg_catalog.pg_type e WHERE t.oid = $1 and t.typelem = e.oid
2021-07-12 17:03:21.601 MSK [22188] DETAIL:  parameters: $1 = '1003'
2021-07-12 17:03:21.602 MSK [22188] LOG:  duration: 1.610 ms
2021-07-12 17:03:21.611 MSK [22188] LOG:  duration: 3.983 ms  parse <unnamed>: select p.*

	from respondent p

	where exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'EMAIL')

	  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'SMS')

	  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'PUSH')

	  and p.space_id = 1

	  and p.deleted_at is null

	limit 12
2021-07-12 17:03:21.624 MSK [22188] LOG:  duration: 12.068 ms  bind <unnamed>: select p.*

	from respondent p

	where exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'EMAIL')

	  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'SMS')

	  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'PUSH')

	  and p.space_id = 1

	  and p.deleted_at is null

	limit 12
2021-07-12 17:03:21.625 MSK [22188] LOG:  execute <unnamed>: select p.*

	from respondent p

	where exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'EMAIL')

	  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'SMS')

	  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'PUSH')

	  and p.space_id = 1

	  and p.deleted_at is null

	limit 12
2021-07-12 17:03:21.626 MSK [22188] LOG:  duration: 0.968 ms
2021-07-12 17:03:21.630 MSK [22188] LOG:  duration: 0.461 ms  parse <unnamed>: SELECT c.oid, a.attnum, a.attname, c.relname, n.nspname, a.attnotnull OR (t.typtype = 'd' AND t.typnotnull), a.attidentity != '' OR pg_catalog.pg_get_expr(d.adbin, d.adrelid) LIKE '%nextval(%' FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON (c.relnamespace = n.oid) JOIN pg_catalog.pg_attribute a ON (c.oid = a.attrelid) JOIN pg_catalog.pg_type t ON (a.atttypid = t.oid) LEFT JOIN pg_catalog.pg_attrdef d ON (d.adrelid = a.attrelid AND d.adnum = a.attnum) JOIN (SELECT 461778 AS oid , 1 AS attnum UNION ALL SELECT 461778, 2 UNION ALL SELECT 461778, 3 UNION ALL SELECT 461778, 4 UNION ALL SELECT 461778, 5 UNION ALL SELECT 461778, 6 UNION ALL SELECT 461778, 7 UNION ALL SELECT 461778, 8 UNION ALL SELECT 461778, 9 UNION ALL SELECT 461778, 10 UNION ALL SELECT 461778, 11 UNION ALL SELECT 461778, 12 UNION ALL SELECT 461778, 13 UNION ALL SELECT 461778, 14 UNION ALL SELECT 461778, 15 UNION ALL SELECT 461778, 16 UNION ALL SELECT 461778, 17) vals ON (c.oid = vals.oid AND a.attnum = vals.attnum) 
2021-07-12 17:03:21.638 MSK [22188] LOG:  duration: 7.459 ms  bind <unnamed>: SELECT c.oid, a.attnum, a.attname, c.relname, n.nspname, a.attnotnull OR (t.typtype = 'd' AND t.typnotnull), a.attidentity != '' OR pg_catalog.pg_get_expr(d.adbin, d.adrelid) LIKE '%nextval(%' FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON (c.relnamespace = n.oid) JOIN pg_catalog.pg_attribute a ON (c.oid = a.attrelid) JOIN pg_catalog.pg_type t ON (a.atttypid = t.oid) LEFT JOIN pg_catalog.pg_attrdef d ON (d.adrelid = a.attrelid AND d.adnum = a.attnum) JOIN (SELECT 461778 AS oid , 1 AS attnum UNION ALL SELECT 461778, 2 UNION ALL SELECT 461778, 3 UNION ALL SELECT 461778, 4 UNION ALL SELECT 461778, 5 UNION ALL SELECT 461778, 6 UNION ALL SELECT 461778, 7 UNION ALL SELECT 461778, 8 UNION ALL SELECT 461778, 9 UNION ALL SELECT 461778, 10 UNION ALL SELECT 461778, 11 UNION ALL SELECT 461778, 12 UNION ALL SELECT 461778, 13 UNION ALL SELECT 461778, 14 UNION ALL SELECT 461778, 15 UNION ALL SELECT 461778, 16 UNION ALL SELECT 461778, 17) vals ON (c.oid = vals.oid AND a.attnum = vals.attnum) 
2021-07-12 17:03:21.639 MSK [22188] LOG:  execute <unnamed>: SELECT c.oid, a.attnum, a.attname, c.relname, n.nspname, a.attnotnull OR (t.typtype = 'd' AND t.typnotnull), a.attidentity != '' OR pg_catalog.pg_get_expr(d.adbin, d.adrelid) LIKE '%nextval(%' FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON (c.relnamespace = n.oid) JOIN pg_catalog.pg_attribute a ON (c.oid = a.attrelid) JOIN pg_catalog.pg_type t ON (a.atttypid = t.oid) LEFT JOIN pg_catalog.pg_attrdef d ON (d.adrelid = a.attrelid AND d.adnum = a.attnum) JOIN (SELECT 461778 AS oid , 1 AS attnum UNION ALL SELECT 461778, 2 UNION ALL SELECT 461778, 3 UNION ALL SELECT 461778, 4 UNION ALL SELECT 461778, 5 UNION ALL SELECT 461778, 6 UNION ALL SELECT 461778, 7 UNION ALL SELECT 461778, 8 UNION ALL SELECT 461778, 9 UNION ALL SELECT 461778, 10 UNION ALL SELECT 461778, 11 UNION ALL SELECT 461778, 12 UNION ALL SELECT 461778, 13 UNION ALL SELECT 461778, 14 UNION ALL SELECT 461778, 15 UNION ALL SELECT 461778, 16 UNION ALL SELECT 461778, 17) vals ON (c.oid = vals.oid AND a.attnum = vals.attnum) 
2021-07-12 17:03:21.640 MSK [22188] LOG:  duration: 1.196 ms
2021-07-12 17:03:21.649 MSK [22188] LOG:  duration: 0.267 ms  parse <unnamed>: SELECT n.nspname = ANY(current_schemas(true)), n.nspname, t.typname FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid WHERE t.oid = $1
2021-07-12 17:03:21.651 MSK [22188] LOG:  duration: 0.323 ms  bind <unnamed>: SELECT n.nspname = ANY(current_schemas(true)), n.nspname, t.typname FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid WHERE t.oid = $1
2021-07-12 17:03:21.651 MSK [22188] DETAIL:  parameters: $1 = '3802'
2021-07-12 17:03:21.653 MSK [22188] LOG:  execute <unnamed>: SELECT n.nspname = ANY(current_schemas(true)), n.nspname, t.typname FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid WHERE t.oid = $1
2021-07-12 17:03:21.653 MSK [22188] DETAIL:  parameters: $1 = '3802'
2021-07-12 17:03:21.654 MSK [22188] LOG:  duration: 1.867 ms
2021-07-12 17:03:21.657 MSK [22188] LOG:  duration: 1.885 ms  parse <unnamed>: SELECT typinput='array_in'::regproc, typtype   FROM pg_catalog.pg_type   LEFT   JOIN (select ns.oid as nspoid, ns.nspname, r.r           from pg_namespace as ns           join ( select s.r, (current_schemas(false))[s.r] as nspname                    from generate_series(1, array_upper(current_schemas(false), 1)) as s(r) ) as r          using ( nspname )        ) as sp     ON sp.nspoid = typnamespace  WHERE typname = $1  ORDER BY sp.r, pg_type.oid DESC LIMIT 1
2021-07-12 17:03:21.658 MSK [22188] LOG:  duration: 0.410 ms  bind <unnamed>: SELECT typinput='array_in'::regproc, typtype   FROM pg_catalog.pg_type   LEFT   JOIN (select ns.oid as nspoid, ns.nspname, r.r           from pg_namespace as ns           join ( select s.r, (current_schemas(false))[s.r] as nspname                    from generate_series(1, array_upper(current_schemas(false), 1)) as s(r) ) as r          using ( nspname )        ) as sp     ON sp.nspoid = typnamespace  WHERE typname = $1  ORDER BY sp.r, pg_type.oid DESC LIMIT 1
2021-07-12 17:03:21.658 MSK [22188] DETAIL:  parameters: $1 = 'jsonb'
2021-07-12 17:03:21.659 MSK [22188] LOG:  execute <unnamed>: SELECT typinput='array_in'::regproc, typtype   FROM pg_catalog.pg_type   LEFT   JOIN (select ns.oid as nspoid, ns.nspname, r.r           from pg_namespace as ns           join ( select s.r, (current_schemas(false))[s.r] as nspname                    from generate_series(1, array_upper(current_schemas(false), 1)) as s(r) ) as r          using ( nspname )        ) as sp     ON sp.nspoid = typnamespace  WHERE typname = $1  ORDER BY sp.r, pg_type.oid DESC LIMIT 1
2021-07-12 17:03:21.659 MSK [22188] DETAIL:  parameters: $1 = 'jsonb'
2021-07-12 17:03:21.660 MSK [22188] LOG:  duration: 1.374 ms
2021-07-12 17:03:21.698 MSK [22188] LOG:  duration: 0.074 ms  parse <unnamed>: SHOW TRANSACTION ISOLATION LEVEL
2021-07-12 17:03:21.698 MSK [22188] LOG:  duration: 0.018 ms  bind <unnamed>: SHOW TRANSACTION ISOLATION LEVEL
2021-07-12 17:03:21.699 MSK [22188] LOG:  execute <unnamed>: SHOW TRANSACTION ISOLATION LEVEL
2021-07-12 17:03:21.700 MSK [22188] LOG:  duration: 0.854 ms
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083407
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
да,там видно что идут лишние селекты - это инициализируются коллекции- но они там ничтожно мало же занимают= откуда почти 7 секунд взялось непонятно
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083414
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
O_79_O
откуда почти 7 секунд взялось непонятно

автор2021-07-12 16:55:35.238 MSK [7888] LOG: execute <unnamed>/C_42: select count(*) from respondent p where exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'EMAIL') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'SMS') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'PUSH') and p.space_id = 1 and p.deleted_at is null
2021-07-12 16:55:41.657 MSK [7888] LOG: duration: 6419.398 ms
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083416
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Melkij
O_79_O
откуда почти 7 секунд взялось непонятно

автор2021-07-12 16:55:35.238 MSK [7888] LOG: execute <unnamed>/C_42: select count(*) from respondent p where exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'EMAIL') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'SMS') and exists (select from respondent_channel rc where p.id=rc.respondent_id and rc.channel_type = 'PUSH') and p.space_id = 1 and p.deleted_at is null
2021-07-12 16:55:41.657 MSK [7888] LOG: duration: 6419.398 ms


этот же запрос в консоли
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
Finalize Aggregate  (cost=321825.09..321825.10 rows=1 width=8) (actual time=2905.765..2986.388 rows=1 loops=1)
  ->  Gather  (cost=321824.87..321825.08 rows=2 width=8) (actual time=2905.756..2986.382 rows=3 loops=1)
        Workers Planned: 2
        Workers Launched: 2
        ->  Partial Aggregate  (cost=320824.87..320824.88 rows=1 width=8) (actual time=2856.987..2856.990 rows=1 loops=3)
              ->  Nested Loop  (cost=73937.04..320476.34 rows=139413 width=0) (actual time=401.690..2842.161 rows=111112 loops=3)
                    ->  Nested Loop  (cost=73936.61..209089.50 rows=163592 width=24) (actual time=401.045..1415.931 rows=111112 loops=3)
                          ->  Parallel Hash Join  (cost=73936.18..131764.68 rows=151025 width=16) (actual time=400.262..574.423 rows=111112 loops=3)
                                Hash Cond: (rc_1.respondent_id = rc_2.respondent_id)
                                ->  Parallel Bitmap Heap Scan on respondent_channel rc_1  (cost=11055.91..63468.91 rows=413520 width=8) (actual time=48.222..145.581 rows=333335 loops=3)
                                      Recheck Cond: (channel_type = 'SMS'::text)
                                      Heap Blocks: exact=4083
                                      ->  Bitmap Index Scan on resp_channel_type  (cost=0.00..10807.80 rows=992449 width=0) (actual time=46.315..46.315 rows=1000005 loops=1)
                                            Index Cond: (channel_type = 'SMS'::text)
                                ->  Parallel Hash  (cost=58270.27..58270.27 rows=280960 width=8) (actual time=148.452..148.453 rows=222223 loops=3)
                                      Buckets: 131072  Batches: 16  Memory Usage: 2688kB
                                      ->  Parallel Bitmap Heap Scan on respondent_channel rc_2  (cost=7514.28..58270.27 rows=280960 width=8) (actual time=12.095..85.504 rows=222223 loops=3)
                                            Recheck Cond: (channel_type = 'PUSH'::text)
                                            Heap Blocks: exact=2675
                                            ->  Bitmap Index Scan on resp_channel_type  (cost=0.00..7345.70 rows=674303 width=0) (actual time=34.712..34.712 rows=666670 loops=1)
                                                  Index Cond: (channel_type = 'PUSH'::text)
                          ->  Index Only Scan using respondent_id_channel on respondent_channel rc  (cost=0.43..0.51 rows=1 width=8) (actual time=0.007..0.007 rows=1 loops=333335)
                                Index Cond: ((respondent_id = rc_1.respondent_id) AND (channel_type = 'EMAIL'::text))
                                Heap Fetches: 0
                    ->  Index Scan using respondent_pkey on respondent p  (cost=0.43..0.68 rows=1 width=8) (actual time=0.012..0.012 rows=1 loops=333335)
                          Index Cond: (id = rc.respondent_id)
                          Filter: ((deleted_at IS NULL) AND (space_id = 1))
Planning Time: 1.508 ms
Execution Time: 2986.795 ms



странно почему разница в два раза ну и даже 3 секунды это перебор,можно с этим что то сделать на ваш взгляд?
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083420
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
сделал без аналайза ну и собственно результат на лицо
этот запрос из консоли выдает результат за почти 7 секунд
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083421
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
СОбственно теперь вопрос к знатокам - есть ли какие то способы убыстрить count(*)
( судя по всему нет - я почитал доки постгреса)
и если так ,то может можно как то достать общее количество из первого запроса который выглядит вот так

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
select p.*
from respondent p
where exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'EMAIL')
  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'SMS')
  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'PUSH')
  and p.space_id = 1
  and p.deleted_at is null
limit 12 offset 0
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083431
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
причем count так плохо работает только с этим запросом ,
напрмер с полнотектовым поиском он за 500 мс
Код: plsql
1.
2.
3.
4.
5.
6.
7.
select count(*)
from respondent p
where to_tsvector('russian',
                  coalesce(first_name, '') || ' ' || coalesce(last_name, '') || ' ' || coalesce(patronymic, '') ||
                  ' ' || email) @@ plainto_tsquery('russian', 'Петр')
  and p.space_id = 1
  and p.deleted_at is null
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083438
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
таже самая участь стала и селектом на интерсетах
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
select count(1) from respondent p where p.id in (
  select pc.respondent_id from respondent_channel pc where pc.channel_type ='EMAIL'
  intersect all
  select pc.respondent_id from respondent_channel pc where pc.channel_type = 'SMS'
  intersect all
  select pc.respondent_id from respondent_channel pc where pc.channel_type ='PUSH')
and p.space_id=1
and p.deleted_at is null ;


теже самые 6.5-7 секунд
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083447
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
я так понимаю единственный вменяемый по скорости способ получить количество элементов можно лишь распарсив план ,но там есть допуск около 1%
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083454
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
O_79_O
я так понимаю единственный вменяемый по скорости способ получить количество элементов можно лишь распарсив план ,но там есть допуск около 1%


там допуск и 100% может быть...
это как база себе представляет... что может сильно с реальностью расходится.

Например есть у вас миллион respondent и есть по 500.000 SMS и 500.000 PUSH
база будет предполагать что распределение случайное и соотвественно тех у кого и sms и push есть 250.000
а в реальности их может быть и 0 (у половины только sms а у второй половины только push)
и 500.000 (у 500.000 и SMS и PUSH у вторых 500.000 - ничего).
В обоих случаях explain вам 250.000 ожидаемых строк вернёт.

Так что у этого метода много ограничений и подводных камней.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083457
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Boguk
O_79_O
я так понимаю единственный вменяемый по скорости способ получить количество элементов можно лишь распарсив план ,но там есть допуск около 1%


там допуск и 100% может быть...
это как база себе представляет... что может сильно с реальностью расходится.

Например есть у вас миллион respondent и есть по 500.000 SMS и 500.000 PUSH
база будет предполагать что распределение случайное и соотвественно тех у кого и sms и push есть 250.000
а в реальности их может быть и 0 (у половины только sms а у второй половины только push)
и 500.000 (у 500.000 и SMS и PUSH у вторых 500.000 - ничего).
В обоих случаях explain вам 250.000 ожидаемых строк вернёт.

Так что у этого метода много ограничений и подводных камней.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru

понял ,спасибо за совет)
а что тогда пагинация на постгресе в своем классическом исполнении не возможна получается?
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083458
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
попробовал и такой варинат
Код: plsql
1.
2.
3.
4.
 select p.* ,count(*) over() as total_count 
from respondent p
 where....
limit 12


2.3 секунды но тоже никуда не годится конечно
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083460
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
O_79_O
Maxim Boguk
пропущено...


там допуск и 100% может быть...
это как база себе представляет... что может сильно с реальностью расходится.

Например есть у вас миллион respondent и есть по 500.000 SMS и 500.000 PUSH
база будет предполагать что распределение случайное и соотвественно тех у кого и sms и push есть 250.000
а в реальности их может быть и 0 (у половины только sms а у второй половины только push)
и 500.000 (у 500.000 и SMS и PUSH у вторых 500.000 - ничего).
В обоих случаях explain вам 250.000 ожидаемых строк вернёт.

Так что у этого метода много ограничений и подводных камней.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru

понял ,спасибо за совет)
а что тогда пагинация на постгресе в своем классическом исполнении не возможна получается?


А она ни на какой базе не возможна на хоть сколько то разумных обьемах...
count(*) по 1.000.000 будет работать ВСЕГДА приблизително столько же сколько select * по этим же миллионам строк (и никакая база вам это не ускорит).
Потому что 90% времени это найти нужные вам строки а подсчитать их или отдать как есть - в пределах погрешности.

Более того - никто уже не делает пагинацию больше чем на 5-10 страниц потому что это просто никому не нужно в реальности.
Ну вот будет у вас пагинация на 10000 страниц... вот кому и какая прикладная для этого польза?

Особенно учитывая тот милый факт (про который алогеты "пагинация на постгресе в своем классическом исполнении" не помнят) что она никогда не будет корректно работать на базе в которой идёт запись в используемые в запросе таблицы.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083461
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
O_79_O
таже самая участь стала и селектом на интерсетах
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
select count(1) from respondent p where p.id in (
  select pc.respondent_id from respondent_channel pc where pc.channel_type ='EMAIL'
  intersect all
  select pc.respondent_id from respondent_channel pc where pc.channel_type = 'SMS'
  intersect all
  select pc.respondent_id from respondent_channel pc where pc.channel_type ='PUSH')
and p.space_id=1
and p.deleted_at is null ;


теже самые 6.5-7 секунд


Что вполне ожидаемо потому что количество строк к пересчёту округлённо тоже самое или даже выше тут.
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083463
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
O_79_O
причем count так плохо работает только с этим запросом ,
напрмер с полнотектовым поиском он за 500 мс
Код: plsql
1.
2.
3.
4.
5.
6.
7.
select count(*)
from respondent p
where to_tsvector('russian',
                  coalesce(first_name, '') || ' ' || coalesce(last_name, '') || ' ' || coalesce(patronymic, '') ||
                  ' ' || email) @@ plainto_tsquery('russian', 'Петр')
  and p.space_id = 1
  and p.deleted_at is null



Так тут строк намного меньше обрабатывать в процессе надо.
count(*) с итогом в 1000.000 вероятнее всего будет не менее чем в 1000 раз медленее чем count(*) с итогом в 1000
если запрос одной структуры.
Это не count(*) плохо работает а запрос на выборку сложную 300.000 строк не быстрый выходит.

Я бы еще включил track_io_timing в конфиге и делал бы explain (analyze,costs,buffers,timing) запросов
может у вас 3/4 времени работа с диском занимает и тогда просто базе надо больше памяти будет выдать и все ускорится заметно.


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083466
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Boguk,
включил в конфигах что вы сказали
Код: plsql
1.
2.
3.
4.
5.
6.
7.
explain (analyze,costs,buffers,timing)
select count(*) from respondent p
where exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'EMAIL')
  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'SMS')
  and exists(select from respondent_channel rc where p.id = rc.respondent_id and rc.channel_type = 'PUSH')
  and p.space_id = 1
  and p.deleted_at is null



запрос

аналитика
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
Finalize Aggregate  (cost=321825.09..321825.10 rows=1 width=8) (actual time=2868.095..2936.541 rows=1 loops=1)
"  Buffers: shared hit=1744410 read=611001, temp read=5608 written=5744"
  I/O Timings: read=4738.084
  ->  Gather  (cost=321824.87..321825.08 rows=2 width=8) (actual time=2866.772..2936.513 rows=3 loops=1)
        Workers Planned: 2
        Workers Launched: 2
"        Buffers: shared hit=1744410 read=611001, temp read=5608 written=5744"
        I/O Timings: read=4738.084
        ->  Partial Aggregate  (cost=320824.87..320824.88 rows=1 width=8) (actual time=2841.225..2841.229 rows=1 loops=3)
"              Buffers: shared hit=1744410 read=611001, temp read=5608 written=5744"
              I/O Timings: read=4738.084
              ->  Nested Loop  (cost=73937.04..320476.34 rows=139413 width=0) (actual time=423.751..2826.364 rows=111112 loops=3)
"                    Buffers: shared hit=1744410 read=611001, temp read=5608 written=5744"
                    I/O Timings: read=4738.084
                    ->  Nested Loop  (cost=73936.61..209089.50 rows=163592 width=24) (actual time=423.098..1411.921 rows=111112 loops=3)
"                          Buffers: shared hit=815247 read=206822, temp read=5608 written=5744"
                          I/O Timings: read=1704.003
                          ->  Parallel Hash Join  (cost=73936.18..131764.68 rows=151025 width=16) (actual time=422.422..590.180 rows=111112 loops=3)
                                Hash Cond: (rc_1.respondent_id = rc_2.respondent_id)
"                                Buffers: shared hit=73 read=21986, temp read=5608 written=5744"
                                I/O Timings: read=348.839
                                ->  Parallel Bitmap Heap Scan on respondent_channel rc_1  (cost=11055.91..63468.91 rows=413520 width=8) (actual time=41.168..177.346 rows=333335 loops=3)
                                      Recheck Cond: (channel_type = 'SMS'::text)
                                      Heap Blocks: exact=4135
                                      Buffers: shared hit=2 read=13190
                                      I/O Timings: read=230.265
                                      ->  Bitmap Index Scan on resp_channel_type  (cost=0.00..10807.80 rows=992449 width=0) (actual time=39.600..39.600 rows=1000005 loops=1)
                                            Index Cond: (channel_type = 'SMS'::text)
                                            Buffers: shared hit=2 read=843
                                            I/O Timings: read=9.358
                                ->  Parallel Hash  (cost=58270.27..58270.27 rows=280960 width=8) (actual time=135.766..135.767 rows=222223 loops=3)
                                      Buckets: 131072  Batches: 16  Memory Usage: 2720kB
"                                      Buffers: shared read=8796, temp written=2260"
                                      I/O Timings: read=118.574
                                      ->  Parallel Bitmap Heap Scan on respondent_channel rc_2  (cost=7514.28..58270.27 rows=280960 width=8) (actual time=10.800..77.454 rows=222223 loops=3)
                                            Recheck Cond: (channel_type = 'PUSH'::text)
                                            Heap Blocks: exact=2791
                                            Buffers: shared read=8796
                                            I/O Timings: read=118.574
                                            ->  Bitmap Index Scan on resp_channel_type  (cost=0.00..7345.70 rows=674303 width=0) (actual time=30.813..30.813 rows=666670 loops=1)
                                                  Index Cond: (channel_type = 'PUSH'::text)
                                                  Buffers: shared read=564
                                                  I/O Timings: read=7.725
                          ->  Index Only Scan using respondent_id_channel on respondent_channel rc  (cost=0.43..0.51 rows=1 width=8) (actual time=0.007..0.007 rows=1 loops=333335)
                                Index Cond: ((respondent_id = rc_1.respondent_id) AND (channel_type = 'EMAIL'::text))
                                Heap Fetches: 0
                                Buffers: shared hit=815174 read=184836
                                I/O Timings: read=1355.164
                    ->  Index Scan using respondent_pkey on respondent p  (cost=0.43..0.68 rows=1 width=8) (actual time=0.012..0.012 rows=1 loops=333335)
                          Index Cond: (id = rc.respondent_id)
                          Filter: ((deleted_at IS NULL) AND (space_id = 1))
                          Buffers: shared hit=929163 read=404179
                          I/O Timings: read=3034.081
Planning:
  Buffers: shared hit=358 read=58
  I/O Timings: read=6.354
Planning Time: 13.222 ms
Execution Time: 2936.886 ms
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083469
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
O_79_O,

ну вот 1)у вас оно мало того что временные файлы пишет
так ещё и большую часть времени запроса читает данные с диска.

Хотите быстрее
1)ставим work_mem в 32MB
2)ставим shared_buffers в 2GB хотя бы (я надеюсь что у вас локально 8GB хотя бы есть.. если есть 16GB то 4GB shared buffers)
3)ставим random_page_cost=1.1
4)перезапускаем базу
5)делает этот же самый explain (analyze,costs,buffers,timing) не 1 раз а раза 3-4 пока время выполенения не перестанет меняться.
Смотрим какое время получилось.


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083471
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Boguk
O_79_O,

ну вот 1)у вас оно мало того что временные файлы пишет
так ещё и большую часть времени запроса читает данные с диска.

Хотите быстрее
1)ставим work_mem в 32MB
2)ставим shared_buffers в 2GB хотя бы (я надеюсь что у вас локально 8GB хотя бы есть.. если есть 16GB то 4GB shared buffers)
3)ставим random_page_cost=1.1
4)перезапускаем базу
5)делает этот же самый explain (analyze,costs,buffers,timing) не 1 раз а раза 3-4 пока время выполенения не перестанет меняться.
Смотрим какое время получилось.


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru

спасибо большее буду пробовать ,завтра отпишусь что вышло
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083614
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Boguk,большое спасибо за советы- вообщем стало быстрее где то раза в два раза.ПРактически влез в SLA

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
Finalize Aggregate  (cost=211449.40..211449.41 rows=1 width=8) (actual time=1069.829..1096.667 rows=1 loops=1)
  Buffers: shared hit=1372056
  ->  Gather  (cost=211449.18..211449.39 rows=2 width=8) (actual time=1066.905..1096.656 rows=3 loops=1)
        Workers Planned: 2
        Workers Launched: 2
        Buffers: shared hit=1372056
        ->  Partial Aggregate  (cost=210449.18..210449.19 rows=1 width=8) (actual time=1037.757..1038.375 rows=1 loops=3)
              Buffers: shared hit=1372056
              ->  Nested Loop  (cost=69833.31..210100.65 rows=139413 width=0) (actual time=360.884..1028.385 rows=111112 loops=3)
                    Buffers: shared hit=1372056
                    ->  Parallel Hash Join  (cost=69832.88..126393.89 rows=163592 width=24) (actual time=360.858..698.457 rows=111112 loops=3)
                          Hash Cond: (rc.respondent_id = rc_1.respondent_id)
                          Buffers: shared hit=38714
                          ->  Parallel Index Only Scan using respondent_id_channel on respondent_channel rc  (cost=0.43..52754.92 rows=833305 width=8) (actual time=0.518..131.214 rows=666670 loops=3)
                                Index Cond: (channel_type = 'EMAIL'::text)
                                Heap Fetches: 0
                                Buffers: shared hit=15332
                          ->  Parallel Hash  (cost=67944.64..67944.64 rows=151025 width=16) (actual time=359.555..360.145 rows=111112 loops=3)
                                Buckets: 524288  Batches: 1  Memory Usage: 19776kB
                                Buffers: shared hit=23314
                                ->  Parallel Hash Join  (cost=31651.40..67944.64 rows=151025 width=16) (actual time=119.127..321.695 rows=111112 loops=3)
                                      Hash Cond: (rc_1.respondent_id = rc_2.respondent_id)
                                      Buffers: shared hit=23314
                                      ->  Parallel Index Scan using respondent_channel_channel_type on respondent_channel rc_1  (cost=0.43..35208.18 rows=413520 width=8) (actual time=0.059..78.276 rows=333335 loops=3)
                                            Index Cond: (channel_type = 'SMS'::text)
                                            Buffers: shared hit=14022
                                      ->  Parallel Hash  (cost=28138.97..28138.97 rows=280960 width=8) (actual time=117.656..117.657 rows=222223 loops=3)
                                            Buckets: 1048576  Batches: 1  Memory Usage: 34304kB
                                            Buffers: shared hit=9292
                                            ->  Parallel Index Scan using respondent_channel_channel_type on respondent_channel rc_2  (cost=0.43..28138.97 rows=280960 width=8) (actual time=0.202..50.994 rows=222223 loops=3)
                                                  Index Cond: (channel_type = 'PUSH'::text)
                                                  Buffers: shared hit=9292
                    ->  Index Scan using respondent_pkey on respondent p  (cost=0.43..0.51 rows=1 width=8) (actual time=0.003..0.003 rows=1 loops=333335)
                          Index Cond: (id = rc.respondent_id)
                          Filter: ((deleted_at IS NULL) AND (space_id = 1))
                          Buffers: shared hit=1333342
Planning:
  Buffers: shared hit=258
Planning Time: 14.422 ms
Execution Time: 1097.360 ms
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083619
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Максим еще один вопрос хотел спросить,для сортировки по фио я создал вот такой индекс
Код: plsql
1.
create index if not exists fio_respondent on respondent(first_name,last_name,patronymic);



и так же есть индекс
Код: plsql
1.
2.
3.
4.
5.
6.
create index if not exists full_text_search_respondent_gin
  on respondent
  using GIN (to_tsvector('russian', coalesce(first_name, '')
            || ' ' || coalesce(last_name, '')
            || ' ' || coalesce(patronymic, '')
            || ' ' || email));



так вот если я делаю такой запрос
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select p.*
from respondent p
where to_tsvector('russian',
                  coalesce(first_name, '') || ' ' || coalesce(last_name, '') || ' ' || coalesce(patronymic, '') ||
                  ' ' || email) @@ plainto_tsquery('russian', 'Петров')
  and p.space_id = 1
  and p.deleted_at is null
order by first_name,last_name,patronymic DESC
limit 12



не будет ли битри индекс fio_respondent мешать полнотекстовому поиску для которого у меня gin index
full_text_search_respondent_gin

аналитика по этому запросу
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Limit  (cost=75.18..911.88 rows=12 width=276) (actual time=10.302..10.304 rows=12 loops=1)
  Buffers: shared hit=962
  ->  Incremental Sort  (cost=75.18..697324.05 rows=10000 width=276) (actual time=10.300..10.301 rows=12 loops=1)
"        Sort Key: first_name, last_name, patronymic DESC"
"        Presorted Key: first_name, last_name"
        Full-sort Groups: 1  Sort Method: top-N heapsort  Average Memory: 31kB  Peak Memory: 31kB
        Buffers: shared hit=962
        ->  Index Scan using fio_respondent on respondent p  (cost=0.55..696897.15 rows=10000 width=276) (actual time=4.751..10.111 rows=37 loops=1)
"              Filter: ((deleted_at IS NULL) AND (space_id = 1) AND (to_tsvector('russian'::regconfig, ((((((COALESCE(first_name, ''::text) || ' '::text) || COALESCE(last_name, ''::text)) || ' '::text) || COALESCE(patronymic, ''::text)) || ' '::text) || email)) @@ '''петр'''::tsquery))"
              Rows Removed by Filter: 917
              Buffers: shared hit=962
Planning:
  Buffers: shared hit=1
Planning Time: 0.228 ms
Execution Time: 10.331 ms
...
Рейтинг: 0 / 0
Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
    #40083647
O_79_O
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
я так понимаю это опять сложная тема,так как то что я смог нарыть говорит о том ,что слон вроде и может использовать несколько индексов в одном query но только в булевом выражении,что означает ,что если я хочу полнотекст по gin а сортировку по b tree такое не получится
но в любом случае когда считается count(*) используется именно gin это хорошо
когда поиск с лимитом используется btree
когда поиск без лимит планировщик опять использует gin
исходя из этого я предполагаю что эти индексы друг другу не мешают,планировщик сам выберет нужный в зависимости от ситуации
...
Рейтинг: 0 / 0
92 сообщений из 92, показаны все 4 страниц
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Селект с фильтром,который выдаст только те записи котороые удовлетворяют условию
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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