Как оптимизировать этот запрос в Oracle 12.1.0.2? - PullRequest
0 голосов
/ 04 июля 2019

Рассмотрим этот оператор SQL:

select *
  from chamado.servico se
  join chamado.chamado ch on ch.id_servico=se.id_servico
  join chamado.statuschamado sc on sc.id_statuschamado=ch.id_statuschamado
 where sc.id_statuschamado=1
;

Теперь рассмотрим соответствующий план выполнения:

enter image description here

Теперь обратите особое внимание на красную коробку! Предикат фильтра (CH.ID_STATUSCHAMADO=1). Его нет в запросе, и это самая дорогая операция.

Таблица SERVICO содержит менее 200 строк, таблица STATUSCHAMADO содержит менее 10 строк, но таблица CHAMADO содержит более 70000 строк.

Мое намерение с теми объединениями, где нужно выполнять полное сканирование таблиц только на STATUSCHAMADO и SERVICO, что должно было налагать накладные расходы на Oracle.

Что не так в моем утверждении?

Обновление 1

У меня есть следующие индексы:

  1. CHAMADO.ID_CHAMADO (PK)
  2. CHAMADO.ID_SERVICO
  3. CHAMADO.ID_AREAATENDIMENTO
  4. SERVICO.ID_SERVICO (PK)
  5. AREAATENDIMENTO.ID_AREAATENDIMENTO (PK)

1 Ответ

3 голосов
/ 04 июля 2019

«Предикат фильтра (CH.ID_STATUSCHAMADO = 1) ... отсутствует в запросе» - возможно, не напрямую, но именно так все и происходит. Вы присоединяетесь STATUSCHAMADO sc к CHAMADO ch на sc.ID_STATUSCHAMADO = ch.ID_STATUSCHAMADO, тогда в вашем предложении WHERE у вас есть sc.ID_STATUSCHAMADO = 1. База данных достаточно умна, чтобы понять, что sc.ID_STATUSCHAMADO всегда будет 1, и, следовательно, может заменить CHAMADO.ID_STATUSCHAMADO = 1. Вы также можете попробовать поменять поля нового индекса в STATUSCHAMADO - попробуйте его как (ID_STATUSCHAMADO, ID_SERVICO), так и (ID_SERVICO, ID_STATUSCHAMADO). Желаем удачи.

...