Оптимизация Oracle CONNECT BY при использовании с предложением WHERE
Предложение Oracle START WITH ... CONNECT BY
применяется до, применяя условие WHERE
в том же запросе. Таким образом, ограничения WHERE не помогут оптимизировать CONNECT BY
.
Например, следующий запрос, скорее всего, выполнит полное сканирование таблицы (игнорируя селективность на dept_id
):
SELECT * FROM employees
WHERE dept_id = 'SALE'
START WITH manager_id is null
CONNECT BY PRIOR employee_id = manager_id
Я попытался улучшить производительность двумя способами:
запрос A:
SELECT * FROM employees
START WITH manager_id is null AND dept_id = 'SALE'
CONNECT BY PRIOR employee_id = manager_id
запрос B:
SELECT * FROM (
SELECT * FROM employees
WHERE dept_id = 'SALE'
)
START WITH manager_id is null
CONNECT BY PRIOR employee_id = manager_id
Хотя оба запроса выполнялись намного лучше, чем оригинал, в Oracle 10g Release 2 запрос B выполнялся намного лучше, чем A.
У вас была аналогичная оптимизация производительности для рассмотрения в отношении предложений CONNECT BY
и WHERE
? Как бы вы объяснили, что запрос B намного лучше, чем запрос A?
Ответы
Ответ 1
Запрос A начинается с менеджеров отдела продаж, а затем получает всех своих сотрудников. Oracle не "знает", что все возвращенные сотрудниками запросы будут находиться в отделе продаж, поэтому он не может использовать эту информацию для сокращения набора данных для работы перед выполнением CONNECT ОТ.
Query B явно уменьшает набор данных, которые будут обрабатываться только тем сотрудникам в Sales, которые Oracle может сделать до выполнения CONNECT BY.
Ответ 2
Это должно обеспечить максимальную производительность:
CREATE INDEX i_employees_employee_manager_dept ON employees (employee_id,manager_id,dept_id);
CREATE INDEX i_employees_manager_employee_dept ON employees (manager_id,employee_id,dept_id);
SELECT * FROM employees
START WITH manager_id is null AND dept_id = 'SALE'
CONNECT BY PRIOR employee_id = manager_id AND dept_id = 'SALE'
Обратите внимание, что для оптимизации нужно использовать как индекс, так и оба условия AND
.
Ответ 3
Это аналогичный запрос, длинный рассказ короче, он работал быстрее, используя вложенный sql, чем двойной соединитель по предыдущему варианту.
'SELECT level, XMLElement("elemento", XMLAttributes(codigo_funcion as "Codigo",
nombre_funcion as "Nombre",
objetivos as "Objetivos",
descripcion as "Descripción",
''rightHanging'' as "layout"))
FROM (
SELECT * FROM dithe_codigo_funcion
WHERE nodo_raiz = ''PEP''
)
START WITH codigo_funcion = ''PEP''
CONNECT BY PRIOR codigo_funcion = nivel_anterior';
Поэтому моя рекомендация без особого опыта заключается в том, чтобы использовать вложенный sql для фильтрации.
Ответ 4
Каковы индексы для сотрудников? Вам лучше иметь индекс на employeeid. И у вас, вероятно, есть один из них, как объявление employeeid в качестве первичного ключа.
Вы можете получить более высокую производительность с индексом на менеджере. Попробуй. Это должно быть сбалансировано с более низкой производительностью при вставке новых сотрудников или реорганизации управляющих отношений.