17

在同一查询中应用条件之前应用OracleSTART WITH ... CONNECT BY子句。因此, WHERE 约束无助于优化。WHERECONNECT BY

例如,以下查询可能会执行全表扫描(忽略 上的选择性dept_id):

SELECT * FROM employees 
WHERE dept_id = 'SALE'
START WITH manager_id is null
CONNECT BY PRIOR employee_id = manager_id

我尝试通过两种方式提高性能:

查询一:

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 第 2 版中,查询 B 的性能确实比 A 好得多。

CONNECT BY对于andWHERE子句,您是否有类似的性能优化来处理?您如何解释查询 B 比查询 A 做得更好?

4

4 回答 4

17

查询 A 说从销售部门的经理开始,然后让他们的所有员工。Oracle 不“知道”查询返回的所有员工都将在销售部门,因此它不能在执行 CONNECT BY 之前使用该信息来减少要使用的数据集。

查询 B将要处理的数据集显式减少到仅适用于 Sales 中的那些员工,然后 Oracle 可以在执行 CONNECT BY 之前执行这些操作。

于 2009-07-04T10:04:23.263 回答
7

这应该给出最终的性能:

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条件才能使优化工作。

于 2011-12-27T09:25:29.157 回答
2

这是一个类似的查询,长话短说,它使用嵌套 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进行过滤。

于 2013-12-03T21:24:42.217 回答
1

员工的指标是什么?你最好有一个关于employeeid的索引。由于将employeeid 声明为主键,您可能确实有一个。

您也可以使用 managerid 上的索引获得更好的性能。尝试一下。在插入新员工或重组管理关系时,这必须与较慢的性能相平衡。

于 2009-07-04T11:39:15.070 回答