powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Почему используется именно такой loop join?
13 сообщений из 13, страница 1 из 1
Почему используется именно такой loop join?
    #39330657
DPH3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тестирую на разных сценариях очередь.
Есть две таблицы: queue, events
Запрос на получение очередного события:
Код: sql
1.
2.
3.
4.
5.
6.
select q.queue, e.id, e.type, e.data
 from queue q
   join events e on q.queue=e.queue
 where q.state = 'RUNNING' 
 order by e.id asc
 limit 1 for update of e skip locked


индекс events(queue)

В таблице queue 2 записи, условию не удовлетворяет ни одна
В таблице events 2 000 000 записей, все с q.queue=e.queue
При запросе PG делает loop join с перебором по events, что занимает 2 секунды, хотя кажется логичнее делать по queue, с выбором подходящего из events по индексу.

Что я делаю не так, как ускорить такой запрос?

(Аналогичная проблема возникает, когда под условие подходит только одна запись в events, но с максимальным id - тоже приходится сканировать всю таблицу events по первичному ключу, что долго. Понятно, что если подходит запись в event с минимальным id, то все отрабатывает мгновенно и вообще в events обычно мало записей и подходящие находятся сразу, я в основном проверяю corner cases, но реальные).

Заранее спасибо.
...
Рейтинг: 0 / 0
Почему используется именно такой loop join?
    #39330693
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DPH3Тестирую на разных сценариях очередь.
Есть две таблицы: queue, events
Запрос на получение очередного события:
Код: sql
1.
2.
3.
4.
5.
6.
select q.queue, e.id, e.type, e.data
 from queue q
   join events e on q.queue=e.queue
 where q.state = 'RUNNING' 
 order by e.id asc
 limit 1 for update of e skip locked


индекс events(queue)

В таблице queue 2 записи, условию не удовлетворяет ни одна
В таблице events 2 000 000 записей, все с q.queue=e.queue
При запросе PG делает loop join с перебором по events, что занимает 2 секунды, хотя кажется логичнее делать по queue, с выбором подходящего из events по индексу.

Что я делаю не так, как ускорить такой запрос?

(Аналогичная проблема возникает, когда под условие подходит только одна запись в events, но с максимальным id - тоже приходится сканировать всю таблицу events по первичному ключу, что долго. Понятно, что если подходит запись в event с минимальным id, то все отрабатывает мгновенно и вообще в events обычно мало записей и подходящие находятся сразу, я в основном проверяю corner cases, но реальные).

Заранее спасибо.

А если сделать analyze queue; - план не меняется?

--
Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
Почему используется именно такой loop join?
    #39330803
DPH3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,

Нет, не меняется, увы (
...
Рейтинг: 0 / 0
Почему используется именно такой loop join?
    #39330830
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DPH3Maxim Boguk,

Нет, не меняется, увы (

1)а что говори explain analyze на этот запрос?
2)сколько уникальных queue а таблице events ?


PS: вообще привыкайте всегда все такие вопросы сопровождать результатом explain analyze.


--
Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
Почему используется именно такой loop join?
    #39330885
DPH3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,

1. explain analyze:

"Limit (cost=0.43..0.54 rows=1 width=41) (actual time=1781.399..1781.399 rows=1 loops=1)"
" -> LockRows (cost=0.43..137154.11 rows=1234680 width=41) (actual time=1781.399..1781.399 rows=1 loops=1)"
" -> Nested Loop (cost=0.43..124807.31 rows=1234680 width=41) (actual time=1781.394..1781.394 rows=1 loops=1)"
" Join Filter: ((q.queue)::text = (e.queue)::text)"
" Rows Removed by Join Filter: 2469359"
" -> Index Scan using events_pkey on wq_events e (cost=0.43..87765.87 rows=2469360 width=35) (actual time=0.038..1263.381 rows=2469360 loops=1)"
" -> Materialize (cost=0.00..1.04 rows=1 width=15) (actual time=0.000..0.000 rows=1 loops=2469360)"
" -> Seq Scan on queue q (cost=0.00..1.03 rows=1 width=15) (actual time=0.005..0.005 rows=1 loops=1)"
" Filter: (((state)::text = 'RUNNING'::text))"
" Rows Removed by Filter: 1"
"Planning time: 0.606 ms"
"Execution time: 1781.447 ms"

2. В данный момент два queue в events, в одном два значения, в другом - все остальные.
...
Рейтинг: 0 / 0
Почему используется именно такой loop join?
    #39330922
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DPH3Maxim Boguk,

1. explain analyze:

"Limit (cost=0.43..0.54 rows=1 width=41) (actual time=1781.399..1781.399 rows=1 loops=1)"
" -> LockRows (cost=0.43..137154.11 rows=1234680 width=41) (actual time=1781.399..1781.399 rows=1 loops=1)"
" -> Nested Loop (cost=0.43..124807.31 rows=1234680 width=41) (actual time=1781.394..1781.394 rows=1 loops=1)"
" Join Filter: ((q.queue)::text = (e.queue)::text)"
" Rows Removed by Join Filter: 2469359"
" -> Index Scan using events_pkey on wq_events e (cost=0.43..87765.87 rows=2469360 width=35) (actual time=0.038..1263.381 rows=2469360 loops=1)"
" -> Materialize (cost=0.00..1.04 rows=1 width=15) (actual time=0.000..0.000 rows=1 loops=2469360)"
" -> Seq Scan on queue q (cost=0.00..1.03 rows=1 width=15) (actual time=0.005..0.005 rows=1 loops=1)"
" Filter: (((state)::text = 'RUNNING'::text))"
" Rows Removed by Filter: 1"
"Planning time: 0.606 ms"
"Execution time: 1781.447 ms"

2. В данный момент два queue в events, в одном два значения, в другом - все остальные.

1)Вы же написали что "В таблице queue 2 записи, условию не удовлетворяет ни одна" а у вас одна есть.
2)Нельзя построить единый план который бы работал нормально в вашей структуре данных.
База предполагает что e.queue более менее поровну распределены по wq_events
Поэтому база вполне честно считает что она быстро найдет нужную ей запись, а то что у вас данные сильно неровные - не делайте такие данные.

Любой план будет плохо работать на corner cases и ничего вы с этим не сделаете.
База из неких средне-нормальных вариантов план подбирает.

--
Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
Почему используется именно такой loop join?
    #39330953
DPH3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk1)Вы же написали что "В таблице queue 2 записи, условию не удовлетворяет ни одна" а у вас одна есть.

Когда нет ни одной подходящей - та же картинка, ничего не работает.

2)Нельзя построить единый план который бы работал нормально в вашей структуре данных.
База предполагает что e.queue более менее поровну распределены по wq_events
Поэтому база вполне честно считает что она быстро найдет нужную ей запись, а то что у вас данные сильно неровные - не делайте такие данные.

Ок, понял, спасибо большое, буду думать.


--
Maxim Boguk
www.postgresql-consulting.ru [/quot]
...
Рейтинг: 0 / 0
Почему используется именно такой loop join?
    #39330955
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,

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

(этому можно бы было и оптимайзер обучить, будь у них желание)

ПС пгку вообще отдельные таблички ивентов под каждое кваее ведет, и очереди обрабатывает раздельно, без этого вот всего.
...
Рейтинг: 0 / 0
Почему используется именно такой loop join?
    #39330964
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwqMaxim Boguk,

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

(этому можно бы было и оптимайзер обучить, будь у них желание)

ПС пгку вообще отдельные таблички ивентов под каждое кваее ведет, и очереди обрабатывает раздельно, без этого вот всего.
извиняюсь, поправил.

всё смешалось в доме обломских(тм)
...
Рейтинг: 0 / 0
Почему используется именно такой loop join?
    #39330977
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwqесли кваеев всегда мало (что модельно скорее всего так и есть), то нужен индекс (кваее,ивент) и переписать запрос на лейтерал по 50 записей из каждой кваее, с последующим фильтром 50 из отобранных вдоль ивент.

Да это будет работать безусловно.
Но вопрос стоял как ускорить именно такой запрос а не как переписать его по уму :).

PS: автору топика - возьмите PGQ и не извращайтесь. Я пока не видел НИ ОДНОЙ нормальной самописной очереди на Postgres (а посмотрел я их много).

--
Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
Почему используется именно такой loop join?
    #39331143
DPH3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[quot Maxim Boguk]
PS: автору топика - возьмите PGQ и не извращайтесь. Я пока не видел НИ ОДНОЙ нормальной самописной очереди на Postgres (а посмотрел я их много).
[quot]
Увы, в PGQ WorkQueue сделана несколько "сбоку", постоянно создавать и уничтожать очереди тоже не слишком дешево (а у меня по ТЗ до 100 очередей в секунду нужно создавать/удалять, да и очередей может быть очень много), отложенной обработки, насколько я помню, нет вообще, обработку ошибок делать тоже не слишком просто.
Т.е. его можно взять за основу - но слишком много допиливать, текущее решение меня вполне устраивает, просто в некоторых сценариях ведет себя не лучшим способом.
Я довольно много посмотрел вариантов, прежде чем велосипед пилить.
...
Рейтинг: 0 / 0
Почему используется именно такой loop join?
    #39331146
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[quot DPH3][quot Maxim Boguk]
PS: автору топика - возьмите PGQ и не извращайтесь. Я пока не видел НИ ОДНОЙ нормальной самописной очереди на Postgres (а посмотрел я их много).
пропущено...

Вот из-за case corners нормально ваше решение в режиме 100 очередей новых в секунду - работать никогда не будет.
Вообще постоянное создание и drop очередей - это признак того что архитектурно что то не то делают.
Т.е. pgq такой какой он есть именно для того чтобы работать быстро всегда (и таки да он работает быстро), а для этого в таблицах очереди не должно быть никаких странных аномалий с данными.

--
Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
Почему используется именно такой loop join?
    #39331467
DPH3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,

ну, как раз на тех сценариях, где нужна работа с сотней очередей в секунду - все нормально работает. И как раз в тех сценариях, где PGQ без кучи сложных доработок вообще не пригоден.
Просто не хочется для близких задач плодить разные решения - вот и смотрю, когда и для чего еще можно использовать ту же самую очередь.
У PGQ все-таки довольно конкретная ниша для применения.
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Почему используется именно такой loop join?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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