Оптимизация Oracle CONNECT BY при использовании с предложением WHERE
Oracle START WITH ... CONNECT BY
пункт применяется до применение 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?
4 ответов
запрос A говорит, что начните с менеджеров в отделе продаж, а затем получите всех своих сотрудников. Oracle не" знает", что все сотрудники, возвращаемые запрос будет в отделе продаж, поэтому он не может использовать эту информацию, чтобы уменьшить набор данных для работы с Перед выполнением подключения.
Запрос B явно уменьшает набор данных для работы только с теми сотрудниками по продажам, которые Oracle может сделать перед выполнением ПОДКЛЮЧЕНИЕ ПО.
Это должно дать максимальную производительность:
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
условия для оптимизации работы.
это аналогичный запрос, короче говоря, он работал быстрее с помощью вложенного sql, чем опция double connect by prior.
'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 для фильтрации.
каковы индексы по сотрудникам? Вам лучше иметь индекс на employeeid. И у вас, вероятно, есть один из последствий объявления employeeid в качестве первичного ключа.
вы можете получить лучшую производительность с индексом на managerid. Попробовать его. Это должно быть сбалансировано с более низкой производительностью при вставке новых сотрудников или реорганизации отношений управления.