Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / PostgreSQL Новый топик    Ответить
 INNER JOIN ... OR ...  [new]
ilejn
Member

Откуда: Москва
Сообщений: 553
Приветствую уважаемое сообщество,

есть запрос

==
select * from t1 inner join t2 on t1.id=t2.id or t1.idd=t2.idd

==

исполняется над табличками по миллиону записей в каждой

==
ilejn=> \d t1
Table "public.t1"
Column | Type | Collation | Nullable | Default
--------+-------------------+-----------+----------+---------
id | integer | | |
idd | integer | | |
s | character varying | | |
Indexes:
"t1_id_ind" btree (id)
"t1_idd_ind" btree (idd)

ilejn=> \d t2
Table "public.t2"
Column | Type | Collation | Nullable | Default
--------+-------------------+-----------+----------+---------
id | integer | | |
idd | integer | | |
s | character varying | | |
Indexes:
"t2_id_ind" btree (id)
"t2_idd_ind" btree (idd)
==

с вот таким планом

==
QUERY PLAN
---------------------------------------------------------------------------------
Gather (cost=1000.00..15725182688.22 rows=1 width=40)
Workers Planned: 2
-> Nested Loop (cost=0.00..15725181688.12 rows=1 width=40)
Join Filter: ((t1.id = t2.id) OR (t1.idd = t2.idd))
-> Parallel Seq Scan on t2 (cost=0.00..23274.67 rows=416667 width=20)
-> Seq Scan on t1 (cost=0.00..22740.14 rows=1000014 width=20)
JIT:
Functions: 6
Options: Inlining true, Optimization true, Expressions true, Deforming true
==

И занимает его исполнение примерно вечность.

В резалтсете должно быть три строки.

Что делать? JOIN ... OR - это какое-то больное место для PostgreSQL, попробовать переписать запрос?

Версия 12, из ubuntu 20.10 без каких-либо настроек.
13 ноя 20, 15:18    [22231464]     Ответить | Цитировать Сообщить модератору
 Re: INNER JOIN ... OR ...  [new]
Maxim Boguk
Member

Откуда: Melbourne, Австралия
Сообщений: 4395
ilejn,

перепишите на union all из 2х join нормальных.
В таком виде как вы написали так вообще нет возможности нормально ни hash join сделать ни merge join.
Потому план странный и медленный.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
13 ноя 20, 15:44    [22231481]     Ответить | Цитировать Сообщить модератору
 Re: INNER JOIN ... OR ...  [new]
ilejn
Member

Откуда: Москва
Сообщений: 553
Maxim Boguk,

спасибо за ответ.

На самом деле, я пытаюсь понять, как разные СУБД работают с таким запросом.
В идеальном мире можно делать хэш-джойн по двум (более чем одной) функции. Кто-нибудь так умеет? Ну или что-то продвинутое, хотя бы как вы и посоветовали, сдеать два джойна, а потом объединить?
13 ноя 20, 15:50    [22231484]     Ответить | Цитировать Сообщить модератору
 Re: INNER JOIN ... OR ...  [new]
Maxim Boguk
Member

Откуда: Melbourne, Австралия
Сообщений: 4395
ilejn
Maxim Boguk,

спасибо за ответ.

На самом деле, я пытаюсь понять, как разные СУБД работают с таким запросом.
В идеальном мире можно делать хэш-джойн по двум (более чем одной) функции. Кто-нибудь так умеет? Ну или что-то продвинутое, хотя бы как вы и посоветовали, сдеать два джойна, а потом объединить?


Это задача dba/разработчика переписывать те запросы с которыми планировщик базы не справляется в те в которые он справляется.
Слишком уж узкий-нишевый случай чтобы под него специальную (и весьма непростую) инфраструктуру городить замедляя тем самым планирование обычных запросов.
Я не знаю умеет ли такое преобразование хоть одна база на рынке (по вышеуказанным причинам).

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
13 ноя 20, 15:55    [22231489]     Ответить | Цитировать Сообщить модератору
 Re: INNER JOIN ... OR ...  [new]
ilejn
Member

Откуда: Москва
Сообщений: 553
Чтобы не ввести кого-нибудь в заблуждение, решил уточнить, что PgSQL в принципе умеет обрабатывать такие запросы быстро.

План выглядит так

==
ilejn=> explain select * from t1 inner join t2 on t1.id=t2.id or t1.idd=t2.idd;
QUERY PLAN
--------------------------------------------------------------------------------------------------
Gather (cost=5000.93..6880570563.06 rows=34319397 width=40)
Workers Planned: 2
-> Nested Loop (cost=4000.93..6877137623.36 rows=14299749 width=40)
-> Parallel Seq Scan on t2 (cost=0.00..10536.67 rows=416667 width=20)
-> Bitmap Heap Scan on t1 (cost=4000.93..11505.03 rows=500006 width=20)
Recheck Cond: ((id = t2.id) OR (idd = t2.idd))
-> BitmapOr (cost=4000.93..4000.93 rows=500007 width=0)
-> Bitmap Index Scan on t1_id_ind (cost=0.00..3750.48 rows=500006 width=0)
Index Cond: (id = t2.id)
-> Bitmap Index Scan on t1_idd_ind (cost=0.00..0.44 rows=1 width=0)
Index Cond: (idd = t2.idd)
JIT:
Functions: 5
Options: Inlining true, Optimization true, Expressions true, Deforming true
(14 rows)
==
16 ноя 20, 17:14    [22233139]     Ответить | Цитировать Сообщить модератору
Все форумы / PostgreSQL Ответить