|
|
|
LEFT JOIN и IS NULL
|
|||
|---|---|---|---|
|
#18+
Работаю с таким запросом (как обычно кусок, то есть смысла в нем не много): Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. Этот запрос выполняется аж 35 секунд. План следующий: Код: 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. Как видно из плана проблема вот в чем, когда Postgres видит A LEFT JOIN B WHERE B.field IS NULL, он при определении selectivity предиката B.field IS NULL, читает его из просто B.field, и не учитывает тот факт, что в A может быть очень много строк, в B очень мало строк, поэтому в результате LEFT JOIN'а почти все записи будут NULL и selectivity на самом деле будет гораздо выше. Соответственно единственный способ с этим бороться, который я пока вижу, это смотреть что если у нас не INNER JOIN + статистика JOIN'а поля с проверкой на NULL значительно меньше общей статистики (без этой проверки можно получить обратный эффект если B большое - в этом случае postgres правильно считает что selectivity низкое), добавлять к предикату B.field IS NULL что-то типа current_timestamp<>current_timestamp. Тогда план будет нормальным: Код: 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. Но тут соответственно 2 вопроса : a) Может есть более простой способ забороть проблему б) Какой еще проверкой можно значительно повысить selectivity кроме как OR current_timestamp<>current_timestamp? OR 1<>1 и аналогичные уберет оптимизатор. А current_timestamp как мне кажется может overhead в крайних случаях давать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.07.2015, 10:55 |
|
||
|
LEFT JOIN и IS NULL
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, a)для начала всесто left join + IS NULL попробуйте использовать Код: plaintext б)ну можно например Код: plaintext -- Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.07.2015, 11:12 |
|
||
|
LEFT JOIN и IS NULL
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk, Не, так, если t6.p0 IS NULL на t6.k0 IS NULL поменять, то она на ANTI 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. Но мне то надо и те, которые есть в t_52, но у которых p0 IS NULL. Понятно что можно разбить на 2 подзапроса (один с k0 IS NULL, а второй с INNER JOIN t_52 и p0 IS NULL) и их UNION'ить. Но это может быть еще больший оверхед. Что касается abs() < 0, хотелось бы что-то не использующее данные таблиц. Но если что можно и так сделать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.07.2015, 11:20 |
|
||
|
LEFT JOIN и IS NULL
|
|||
|---|---|---|---|
|
#18+
Собственно насколько я читал, not exists и left join с IS NULL начиная с 8.4 выполняются практически одинаково. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.07.2015, 11:21 |
|
||
|
LEFT JOIN и IS NULL
|
|||
|---|---|---|---|
|
#18+
Nitro_JunkieMaxim Boguk, Не, так, если t6.p0 IS NULL на t6.k0 IS NULL поменять, то она на ANTI JOIN переходит: Но мне то надо и те, которые есть в t_52, но у которых p0 IS NULL. пардон не внимательно прочел запрос... вот так вот тогда можно попробовать Код: plaintext На всякий случай вопрос - t6.k0 оно вообще уникальное? Так как если нет то при наличии нескольких одинаковых строк с одинаковыми t6.k0 + t6.p0 IS NULL вы получите дубли в результате вашего запроса. -- Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.07.2015, 12:07 |
|
||
|
LEFT JOIN и IS NULL
|
|||
|---|---|---|---|
|
#18+
Maxim BogukNitro_JunkieMaxim Boguk, Не, так, если t6.p0 IS NULL на t6.k0 IS NULL поменять, то она на ANTI JOIN переходит: Но мне то надо и те, которые есть в t_52, но у которых p0 IS NULL. пардон не внимательно прочел запрос... вот так вот тогда можно попробовать Код: plaintext На всякий случай вопрос - t6.k0 оно вообще уникальное? Так как если нет то при наличии нескольких одинаковых строк с одинаковыми t6.k0 + t6.p0 IS NULL вы получите дубли в результате вашего запроса. -- Maxim Boguk www.postgresql-consulting.ru Так естественно тоже помогает. Код: 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. Но это уже ручное управление планом запроса. Хотелось бы точечно на предикат воздействовать, потому как если из t_52 нужно еще что-то считать, нужно получается еще раз join'ить, а если при этом там "каскадный" join через 3 таблицы.... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.07.2015, 13:01 |
|
||
|
LEFT JOIN и IS NULL
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, LEFT JOIN WHERE IS NULL эквивалентен NOT EXISTS в одном и только в одном случае... если это LEFT JOIN t_52 t6 ON t6.k0=t0.key0 ... WHERE t6.k0 IS NULL У вас же WHERE IS NULL условие совсем другое (и как я уже написал not exists и LEFT JOIN могут давать разное количество строк результата если есть дубли по полю t6.k0). Поэтому и планы разные так как запросы разные по сути. Для поднятия селективности LEFT JOIN условия с т.з. оптимизатора можно например прикрутить LEFT JOIN t_52 t6 ON t6.k0=t0.key0 AND random()>=0 например... ну или еще какую функцию подобную (селективность у всех одинакова), главное чтобы она в константу не фолдилась. -- Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.07.2015, 13:56 |
|
||
|
LEFT JOIN и IS NULL
|
|||
|---|---|---|---|
|
#18+
касательно selectivity: зная вот эти значения Код: plaintext 1. 2. 3. 4. 5. набор каких-то заведомо истинных/ложных условий типа abs(t0.key0)<0, random() = -1 и формулы, по которым вычисляется selectivity and/or двух условий (для and - как произведение selectivity отдельных частей, для or - как сумма минус произведение) можно в принципе извратиться и захардкодить нужное значение если очень надо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.07.2015, 19:11 |
|
||
|
LEFT JOIN и IS NULL
|
|||
|---|---|---|---|
|
#18+
авторSeq Scan on public.t_52 t6 (cost=0.00..0.20 rows=2 width=8) статистика по количеству записей - того. Тухлая. Там же не 2 ровса????? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.08.2015, 09:09 |
|
||
|
LEFT JOIN и IS NULL
|
|||
|---|---|---|---|
|
#18+
Ivan DurakавторSeq Scan on public.t_52 t6 (cost=0.00..0.20 rows=2 width=8) статистика по количеству записей - того. Тухлая. Там же не 2 ровса????? Судя по Код: plaintext 1. 2. 3. 4. PS: При пустой статистике по умолчанию считается 1000 в таблице. -- Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.08.2015, 09:56 |
|
||
|
|

start [/forum/topic.php?fid=53&msg=39018414&tid=1997848]: |
0ms |
get settings: |
10ms |
get forum list: |
20ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
81ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
69ms |
get tp. blocked users: |
2ms |
| others: | 229ms |
| total: | 435ms |

| 0 / 0 |
