Professional Documents
Culture Documents
Optimizer Operations
Objectives
After completing this lesson, you should be able to understand the behavior of the Oracle query
optimizer at the following levels:
• Access path
• Sorts
• Joins
Access Paths
Access paths are the ways in which data is retrieved from the database. Any row can be located
and retrieved with one of the methods mentioned in the slide. Access paths are ways in which
data is retrieved from the database.
In general, index access paths should be used for statements that retrieve a small subset of table
rows, while full scans are more efficient when accessing a large portion of the table. Online
transaction processing (OLTP) applications, which consist of short-running SQL statements with
high selectivity, often are characterized by the use of index access paths. Decision support
systems, on the other hand, tend to use full scans of the relevant objects.
• Lack of index
• Large amount of data
• Small table
Row ID Scans
The row ID of a row specifies the data file and data block containing the row as well as the
location of the row in that block. Locating a row by specifying its row ID is the fastest way to
retrieve a single row, because the exact location of the row in the database is specified.
To access a table by row ID, Oracle Database first obtains the row IDs of the selected rows,
either from the statement’s WHERE clause or through an index scan of one or more of the table’s
indexes. Oracle Database then locates each selected row in the table based on its row ID. This is
generally the second step after retrieving the row ID from an index.
The table access might be required for any columns in the statement that are not present in the
index. Access by row ID does not need to follow every index scan. If the index contains all the
columns needed for the statement, then table access by row ID might not occur.
Note: Due to row migration, a row ID can sometimes point to a different address than the actual
row location, resulting in more than one block being read to locate a row. This is caused by the
value of the PCTFREE initialization parameter, which influences the space reserved for updates,
making the space too small. In this case, an update to a row causes the row to be placed in
another block with a pointer in the original block. The row ID, however, will still have only the
address of the original block.
Index Scans
In this method, the indexed column values specified by the statement are used to retrieve the
row. An index scan retrieves data from an index based on the value of one or more columns in
the index. To perform an index scan, Oracle Database searches the index for the indexed column
values accessed by the statement. If the statement accesses only columns of the index, then
Oracle Database reads the indexed column values directly from the index rather than from the
table.
The index contains not only the indexed value but also the row IDs of rows in the table having
that value. Therefore, if the statement accesses other columns in addition to the indexed
columns, then Oracle Database can find the rows in the table by using either a table access by
row ID or a cluster scan.
Index Unique Scan
An index unique scan returns, at most, a single row ID. Oracle Database performs a unique scan
if a statement contains a UNIQUE or a PRIMARY KEY constraint that guarantees that only a
single row is accessed. This access path is used when all columns of a unique (B-tree) index are
specified with equality conditions. In general, you do not need to use a hint to do a unique scan.
• Join statement
• Join predicate, nonjoin predicate
• Single-row predicate
SELECT c.cust_last_name,c.cust_first_name,
co.country_id, co.country_name
FROM customers c JOIN countries co
ON (c.country_id = co.country_id)
AND ( co.country_id = '52790'
OR c.cust_id = 205);
Join predicate
Nonjoin predicate
Single-row predicate
Join Terminology
A join statement is a select statement with more than one table in the FROM clause.
However, the optimizer uses the techniques usually associated with joins when executing other
kinds of statements where more than one table is referenced (as in subqueries, which are
discussed later in this lesson). This slide gives an example of an SQL:1999–compliant join
statement that is available in Oracle Database.
A join predicate is a predicate in the WHERE clause that combines the columns of two of the
tables in the join.
A nonjoin predicate is a predicate in the WHERE clause that references only one table.
A single-row predicate is an equality predicate on a column with a unique or primary key
constraint, or a column with a unique index without a corresponding constraint. The optimizer
knows that these predicates always return either one row or no rows at all.
The corresponding join that is proprietary to Oracle Database is:
SELECT c.cust_last_name, c.cust_first_name,
co.country_id, co.country_name
FROM customers c , countries co
WHERE c.country_id = co.country_id
AND co.country_id = '52790'
OR c.cust_id = 205;
• Natural join
SELECT c.cust_last_name, co.country_name
FROM customers c NATURAL JOIN countries co;
Outer Joins
Oracle Database supports SQL:1999–compliant join syntax. You can specify RIGHT, LEFT, and
FULL outer joins to create the outer joins as well as using the plus (+) sign (as shown in the next
slide).
A join between two tables that returns the results of the INNER join, as well as unmatched rows
in the left (right) table, is considered a LEFT(RIGHT)OUTER JOIN.
A join between two tables that returns the results of an INNER join, as well as the results of
both the LEFT and RIGHT outer joins, is considered a FULL OUTER JOIN. This is not
intended to improve performance.
The use of the plus (+) sign is still supported.
Rule 1
A single-row predicate forces its row source to be
placed first in the join order.
Rule 2
For outer joins, the table with the outer-joined table
must come after the other table in the join order for
processing the join.
Join Optimization
The number of tables in the join and the specified join predicates determine the number of
possible execution plans. Theoretically, the number of possible execution plans is as follows:
2 2
3 3! = 3 * 2 = 6
4 4! = 4 * 3 * 2 = 24
5 5! = 5 * 4 * 3 * 2 = 120
... ...
Because only the execution plans that follow a join predicate are considered, the number of
possible execution plans usually does not reach this value when the number of tables is greater
than 3. However, joining 20 tables still results in many possible execution plans. Remember that
all tables involved in a join, including those that are hidden in views, count as separate tables.
Join Methods
A join operation combines the output from two row sources (such as tables or views ) and returns
one resulting row source (data set). The Oracle Server supports different join methods such as
the following:
Nested loop join: Useful when small subsets of data are being joined and if the join condition is
an efficient way of accessing the second table.
Hash join: Used for joining large data sets. The optimizer uses the smaller of two tables or data
sources to build a hash table on the join key in memory. It then scans the larger table, probing the
hash table to find the joined rows. This method is best used when the smaller table fits in
available memory. The cost is then limited to a single read pass over the data for the two tables.
Sort-merge join: Can be used to join rows from two independent sources. Hash joins generally
perform better than sort-merge joins. On the other hand, sort-merge joins can perform better than
hash joins if both of the following conditions are met:
• The row sources are already sorted.
• A sort operation does not have to be done.
These methods are covered in the following slides.
Nested loops
2 3
Hash Joins
Hash joins are performed only for equijoins. These are the steps performed for a hash join:
1. The optimizer uses the smaller of two tables or data sources to build a hash table on
the join key in memory.
2. The optimizer then scans the larger table, probing the hash table to find the joined rows.
Basic Execution Plan
HASH JOIN
TABLE ACCESS (..) OF table_A
TABLE ACCESS (..) OF table_B
Performance Considerations
As a general rule, hash joins outperform sort-merge joins. In some cases, a sort-merge join can
outperform a nested loop join; it is even more likely that a hash join will do so.
Hash join
2 3
Sort-Merge Joins
In the sort operations, the two row sources are sorted on the values of the columns used in the
join predicate. If a row source has already been sorted in a previous operation, the
sort-merge operation skips the sort on that row source.
Sorting could make this join technique expensive, especially if sorting cannot be performed in
memory.
The merge operation combines the two sorted row sources to retrieve every pair of rows that
contain matching values for the columns used in the join predicate.
Basic Execution Plan
MERGE (JOIN)
SORT (JOIN)
TABLE ACCESS (…) OF table_A
SORT (JOIN)
TABLE ACCESS (…) OF table_B
Merge 1
Sort 2 3 Sort
4 5
Dimension
tables PRODUCTS CUSTOMERS
SALES
Star Joins
One type of data warehouse design focuses on a star schema. A star schema is characterized by
one or more large fact tables that contain the primary information in the data warehouse and a
number of much smaller dimension tables (or lookup tables), each of which contains information
about the entries for a particular attribute in the fact table.
A star query is a join between a fact table and a number of lookup tables. Each lookup table is
joined to the fact table using a primary key–to–foreign key join, but the lookup tables are not
joined to each other.
Note: Star joins are primarily used in data warehousing applications. For more information on
this topic, see Appendix D (“Data Warehouse Tuning Considerations”).
Noncorrelated Subqueries
A noncorrelated subquery does not contain references to the outer (main) query and can be
executed independently, as in the following example:
SELECT c.*
FROM customers c
WHERE c. country_id IN
(SELECT co.country_id
FROM countries co
WHERE co.country_subregion = 'Asia');
This statement is typically executed as a hash join with the subquery as the outer table. It
retrieves all customers in location “Asia.” This is the execution plan structure:
Execution Plan
---------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=363 Card=6250
Bytes= 918750)
1 0 HASH JOIN (Cost=363 Card=6250 Bytes=918750)
2 1 TABLE ACCESS (FULL) OF 'COUNTRIES' (Cost=1 Card=2
Bytes=28)
3 1 TABLE ACCESS (FULL) OF 'CUSTOMERS' (Cost=360
Card=50000 Bytes=6650000)
Antijoins
An antijoin is a select statement with a subquery with a NOT IN predicate, as in the following
example:
SELECT c.*
FROM customers c
WHERE c.cust_income_level = 'F: 110,000 - 129,999'
AND c.country_id NOT IN
(SELECT co.country_id
FROM countries co
WHERE co.country_subregion = 'Europe');
Execution Plan
-----------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=188 …)
…
3 2 HASH JOIN* (RIGHT ANTI) (Cost=188 …)
…
7 6 TABLE ACCESS (FULL) OF 'COUNTRIES' (TABLE)
(Cost=3 …)
9 8 TABLE ACCESS* (FULL) OF 'CUSTOMERS'(TABLE)
(Cost= …)
Note: This example is abbreviated to avoid showing the parallel execution.
• SORT UNIQUE
• SORT AGGREGATE
• SORT GROUP BY
• SORT JOIN
• SORT ORDER BY
Sort Operations
Sort operations result when users specify an operation that requires a sort. Commonly
encountered operations include the following:
• SORT UNIQUE occurs if a user specifies a DISTINCT clause or if an operation requires
unique values for the next step.
• SORT AGGREGATE does not actually involve a sort. It is used when aggregates are being
computed across the whole set of rows.
• SORT GROUP BY is used when aggregates are being computed for different groups in the
data. The sort is required to separate the rows into different groups.
• SORT JOIN happens during a sort-merge join if the rows need to be sorted by the join
key.
• SORT ORDER BY is required when the statement specifies an ORDER BY that cannot be
satisfied by one of the indexes.
SELECT *
FROM (SELECT prod_id
, prod_name
, prod_list_price
, prod_min_price
FROM products
ORDER BY prod_list_price DESC)
WHERE ROWNUM <= 5;
Top-N SQL
The significance of the Top-N SQL feature is that you do not need to sort a full set if, for
example, you are interested in only the four highest (or lowest) values. If a set is too big to be
sorted in memory, the performance is significantly degraded. This is caused by the I/O to and
from the temporary storage of intermediate results on disk.
If you want to know only the four highest values, you need an array with four slots to scan the
set and keep the four highest values in that array.
The WHERE clause of the statement in the slide is merged into the inline view to prevent the
full PRODUCTS table from being sorted by PROD_LIST_PRICE. This appears in the execution
plan as follows:
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=248 …)
1 0 COUNT (STOPKEY)
2 1 VIEW (Cost=248 Card=10000 Bytes=660000)
3 2 SORT (ORDER BY STOPKEY) (Cost=248 …)
4 3 TABLE ACCESS (FULL) OF 'PRODUCTS' (Cost=109 …)
Summary
This lesson introduced you to performance issues with sorting and with optimizing join
statements.
There are several join operations that Oracle Database supports:
• Nested loop join
• Sort-merge join
• Hash join
• Cluster join
The Oracle optimizer optimizes joins in three phases. First, the optimizer generates a list of
possible join orders. Then, for each possible join order, the best join operation is selected.
Finally, the Oracle optimizer determines the best access path for each row source of the
execution plan.