This document provides tips on improving the performance of your SQL queries. Topics include:
Section D.1, "Optimizing Single-Table Queries" Section D.2, "Optimizing Join Queries" Section D.3, "Optimizing with Order By and Group By Clauses"
The tip examples use the following database schema: Table D-1 Database Schema Examples Tables LOCATION Columns LOC# LOC_NAME EMP SS# NAME JOB_TITLE WORKS_IN DEPT DEPT# NAME BUDGET LOC DEPT# LOC references LOCATION (LOC#) MGR references EMP (SS#) SS# WORKS_IN references DEPT (DEPT#) Primary Keys LOC# Foreign Keys
Tables
Columns MGR
Primary Keys
Foreign Keys
Normally optimizer picks the best execution plan, an optimal order of tables to be joined. In case the optimizer is not producing a good execution plan you can control the order of execution using the HINTS feature SQL. For more information see the Oracle9i Lite SQL Reference. For example, if you want to select the name of each department along with the name of its manager, you can write the query in one of two ways. In the first example which follows, the hint /++ordered++/ says to do the join in the order the tables appear in the FROM clause with attempting to optimize the join order.
SELECT /++ordered++/ d.NAME, e.NAME FROM DEPT d, EMP e WHERE d.MGR = e.SS#
or:
SELECT /++ordered++/ d.NAME, e.NAME FROM EMP e, DEPT d WHERE d.MGR = e.SS#
Suppose that there are 10 departments and 1000 employees, and that the inner table in each query has an index on the join column. In the first query, the first table produces 10 qualifying rows (in this case, the whole table). In the second query, the first table produces 1000 qualifying rows. The first query will access the EMP table 10 times and scan the DEPT table once. The second query will scan the EMP table once but will access the DEPT table 1000 times. Therefore the first query will perform much better. As a rule of thumb, tables should be arranged from smallest effective number rows to largest effective number of rows. The effective row size of a table in a query is obtained by applying the logical conditions that are resolved entirely on that table. In another example, consider a query to retrieve the social security numbers and names of employees in a given location, such as New York. According to the sample schema, the query would have three table references in the FROM clause. The three tables could be ordered in six different ways. Although the result is the same regardless of which order you choose, the performance could be quite different. Suppose the effective row size of the LOCATION table is small, for example select count(*) from LOCATION where LOC_NAME = 'New York' is a small set. Based on the above rules, the LOCATION table should be the first table in the FROM clause. There should be an index on LOCATION.LOC_NAME. Since LOCATION must be joined with DEPT, DEPT should be the second table and there should be an index on the LOC column of DEPT. Similarly, the third table should be EMP and there should be an index on EMP#. You could write this query as:
SELECT /++ordered++/ e.SS#, e.NAME FROM LOCATION l, DEPT d, EMP e WHERE l.LOC_NAME = 'New York' AND l.LOC# = d.LOC AND d.DEPT# = e.WORKS_IN;
becomes:
SELECT c2 FROM t1, t2 WHERE t1.c2 = t2.c1;