与WHERE子句一起使用时优化Oracle CONNECT BY

top*_*hef 16 sql oracle performance select query-optimization

在同一查询中应用条件之前应用Oracle START 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
Run Code Online (Sandbox Code Playgroud)

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

查询A:

SELECT * FROM employees 
START WITH manager_id is null AND dept_id = 'SALE'
CONNECT BY PRIOR employee_id = manager_id
Run Code Online (Sandbox Code Playgroud)

查询B:

SELECT * FROM (
               SELECT * FROM employees 
                WHERE dept_id = 'SALE'
              )
START WITH manager_id is null
CONNECT BY PRIOR employee_id = manager_id
Run Code Online (Sandbox Code Playgroud)

虽然两个查询都比原始查询好得多,但在Oracle 10g第2版中,查询B确实比A更好.

您是否有类似的性能优化来处理CONNECT BYWHERE条款?您如何解释查询B比查询A做得更好?

Ton*_*ews 15

查询A表示从销售部门的经理开始,然后获得所有员工.Oracle不"知道" 所有返回的员工都是查询将在销售部门,因此在执行CONNECT BY之前,它不能使用该信息来减少要使用的数据集.

查询B 明确地将要处理的数据集减少到Sales中的那些员工,然后Oracle可以在执行CONNECT BY之前执行此操作.


小智 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' 
Run Code Online (Sandbox Code Playgroud)

请注意,您确实需要索引和两个AND条件才能使优化工作.