Оптимизация 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. Попробовать его. Это должно быть сбалансировано с более низкой производительностью при вставке новых сотрудников или реорганизации отношений управления.