Oracle START WITH ... CONNECT BY
clause is applied before applying WHERE
condition in the same query. Thus, WHERE constraints won't help optimize CONNECT BY
.
For example, the following query will likely perform full table scan (ignoring selectivity on dept_id
):
SELECT * FROM employees
WHERE dept_id = 'SALE'
START WITH manager_id is null
CONNECT BY PRIOR employee_id = manager_id
I tried to improve performance in 2 ways:
query A:
SELECT * FROM employees
START WITH manager_id is null AND dept_id = 'SALE'
CONNECT BY PRIOR employee_id = manager_id
query B:
SELECT * FROM (
SELECT * FROM employees
WHERE dept_id = 'SALE'
)
START WITH manager_id is null
CONNECT BY PRIOR employee_id = manager_id
While both queries did much better than original, on Oracle 10g Release 2, query B did performed much better than A.
Did you have similar performance optimization to deal with with respect to CONNECT BY
and WHERE
clauses? How would you explain query B doing much better than query A?
A where clause will generally increase the performance of the database. Generally, it is more expensive to return data and filter in the application. The database can optimize the query, using indexes and partitions. The database may be running in parallel, executing the query in parallel.
The Oracle "with" clause will help performance in situations where your query contains several identical sub queries. Instead of re-computing the repeating sub queries, it will query or aggregate once, assign a name to the resulting data and refer to it.
Partitioning your data and creating local partitioned indexes can improve your query performance. On a partitioned table, each partition has its own set of index tables. Effectively, there are multiple indexes, but the results from each are combined as necessary to produce the final result set.
Introduction to the Oracle HAVING clause In this statement, the HAVING clause appears immediately after the GROUP BY clause. If you use the HAVING clause without the GROUP BY clause, the HAVING clause works like the WHERE clause. Note that the HAVING clause filters groups of rows while the WHERE clause filters rows.
Query A says start with managers in the Sales department and then get all their employees. Oracle doesn't "know" that all the employees returned be the query will be in the Sales department, so it can't use that information to reduce the set of data to work with before performing the CONNECT BY.
Query B explicitly reduces the set of data to be worked on to just those employees in Sales, which Oracle can then do before performing the CONNECT BY.
This should give the ultimate performance:
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'
Note that you do need both index and both AND
conditions for the optimization to work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With