Oracle производительность и присоединиться к ИЛИ - PullRequest
0 голосов
/ 18 июня 2020

У меня иногда возникают проблемы с подключением и предложением «ИЛИ». Пример упрощен, но он показывает смысл вопроса:

select a.ID, b.ID
from table a
  left join table2 b on (a.ID = b.ID)

Результаты: 20 тыс. Строк и 0,2 секунды

select a.ID, b.ID
from table a
  left join table2 b on (a.ID2 = b.ID2)

Результаты: 20 тыс. Строк и 0,2 с

select a.ID, b.ID
from table a
  left join table2 b on (a.ID = b.ID or a.ID2 = b.ID2)

Результаты: 20 тыс. Строк, время 30 с!

Платформа: Oracle 11xe linux.

Почему такая разница во времени выполнения?

Ответы [ 3 ]

3 голосов
/ 18 июня 2020

Вместо ИЛИ попробуйте использовать UNION

select a.ID, b.ID
from tablea a
left join tableb b a.ID = b.ID
UNION 
select a.ID, b.ID
from tablea a
left tableb b join a.ID2 = b.ID2

или UNION ALL

select a.ID, b.ID
from tablea a
left join tableb b a.ID = b.ID
UNION  ALL
select a.ID, b.ID
from tablea a
left tableb b join a.ID2 = b.ID2
1 голос
/ 22 июня 2020
Ответ

scaisEdge предоставляет конкретное c решение, но также стоит изучить общую c причину, по которой условия OR в соединениях могут вызывать проблемы с производительностью - условия OR не позволяют оптимизатору использовать соединения ha sh.

Ha sh объединения обычно являются самым быстрым способом объединить большой процент данных. (Ваши таблицы могут быть небольшими, но, поскольку нет фильтров, они обрабатывают большой процент данных.) Но ha sh объединений могут работать только с условиями равенства. Чтобы обработать условие OR, Oracle должен будет использовать более медленный метод соединения, такой как сортировка слияния или вложенный l oop.

Если вы думаете о количестве строк из двух таблиц как M и N, соединение ha sh может (теоретически) выполняться в операциях M+N, тогда как объединение слияния сортировки может выполняться в M*LOG(N). Если вам интересно, этот пример главы содержит более подробную информацию о различных типах соединения Oracle и о том, как их производительность сравнивается.

Версия UNION должна присоединяться к таблицам дважды , но два быстрых соединения могут быть лучше одного медленного. Oracle не всегда может преобразовать OR в UNION или UNION ALL, потому что эти две версии могут не обязательно возвращать те же строки, что и другие ваши запросы. Например, альтернативы UNION по-разному обрабатывают повторяющиеся строки. (Но, возможно, вы знаете что-то о своих данных, чего не знает Oracle, поэтому запросы все равно могут работать для вас.)

Это знание полезно, потому что OR не является медленным по своей сути, и мы этого не делаем. Я всегда хочу этого избежать. Если OR - это просто часть доступа к индексу или часть соединения, которое в любом случае не будет использовать соединение ha sh, тогда в этом нет ничего плохого.

0 голосов
/ 19 июня 2020

На самом деле невозможно ответить на такой вопрос о производительности без плана выполнения. Если бы мне пришлось угадывать, я бы заподозрил, что у вас есть индекс на a.id и b.id, но не на a.id2 и b.id2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...