Query Hints
Query Hints
====================================
The following table lists each hint discussed in this chapter and the use of the
hint.
Hint Use
===================================================================================
======
==================================== Specifying a Hint
===========================
The table in the preceding code snippet is the table name to perform a full table
scan on, or
the alias for the table if you specified an alias in the FROM clause, as shown
here:
In this example, if there were an index on the DeptNo column, a full table scan
would be
performed. The hint is not required to be uppercase.
By default, hints only affect the code block in which they appear. If you hint the
access of the
EMP table in a query that is part of a UNION operation, the other queries within
the UNION will
not be affected by your hint. If you want all of the unioned queries to use the
same hint, you will
need to specify the hint in each of the queries.
You can specify the query block name in hints to specify the query block to which
the hint
applies. Thus, in an outer query you can specify a hint that applies to a subquery.
The syntax for
the queryblock argument of the hint syntax is in the form
@queryblock
You can use more than one hint at a time, although this may cause some or all of
the hints to be
ignored. Separate hints with spaces, are shown here:
The (table) in this code snippet is the table name to perform the full scan and
cache on.
====================== When Using an Alias, Hint the Alias, Not the Table
=================================
When you use aliases on a given table that you want to use in a hint, you must
specify the alias
and not the table name in the hint. If you specify the table name in the hint when
an alias is used,
the hint is not used.
The (table) in this code snippet has to be replaced with the alias that follows,
since the query
uses an alias. If an alias is used, the alias must be used in the hint or the hint
will not work.
The first step is to flush the shared pool to clear the cache of older SQL
statements:
The FIRST_ROWS hint generally forces the use of indexes, which under normal
circumstances may not have been used
The FIRST_ROWS hint is ignored in UPDATE and DELETE statements, since all rows of
the
query must be updated or deleted. It is also ignored when any grouping statement is
used (GROUP
BY, DISTINCT, INTERSECT, MINUS, UNION
Syntax
select /*+ FIRST_ROWS(n) */ column1, �
Example
select /*+ FIRST_ROWS */ empno, ename, deptno
from emp
where deptno = 1;
Example
The ALL_ROWS (best throughput) hint directs a query to optimize a query on the
basis of
retrieving all of the rows the fastest.
Syntax
select /*+ ALL_ROWS */ column1, �
Example
The FULL hint directs a query to override the optimizer and perform a full table
scan on the
specified table in the hint.
Syntax
select /*+ FULL(table) */ column1,�
Here, (table) is the table name to perform the full scan on. If an alias is used,
the alias must be
used in the hint or it will not work.
Note that you should only specify the table name in the hint, not the schema name.
Example
The INDEX hint is frequently used to force one or more indexes to be executed for a
given query.
Oracle generally chooses the correct index or indexes with the optimizer, but when
the optimizer
chooses the wrong index or no index at all, this hint is excellent
Syntax
select /*+ INDEX (table index1, index2�) */ column1, �
Example
In this example, the deptno_idx index on the emp table will be used.
Example
In the second example, Oracle may use the deptno_idx index, or the empno_idx index,
or a
merge of both of them. We have placed these choices in the optimizer�s hands to
decipher the
best choice.
Example
In this example, no index is specified. Oracle now weighs all of the possible
indexes that are
available and chooses one or more to be used
As of Oracle Database 10g, you can specify column names as part of the INDEX hint.
The
columns can be prefixed with the table names (not table aliase
Syntax
Example
The NO_INDEX hint disallows the optimizer from using a specified index. This is a
great hint
for tuning queries with multiple indexes. While you may not know which of multiple
indexes to
drive the query with, you might know which ones that you don�t want the optimizer
to use
Syntax
In this example, the deptno_idx index on the emp table will not be used. If the
NO_INDEX
hint is used and no index is specified, a full table scan will be performed.
If the NO_INDEX and a conflicting hint (such as INDEX) are specified for the same
index, then both hints are ignored
(as in the example that follows).
Example
select /*+ NO_INDEX (emp deptno_idx) INDEX (emp deptno_idx) */ ename, deptno
from emp
where deptno = 1;
========================================= The INDEX_ JOIN Hint
==================================
The INDEX_JOIN hint merges separate indexes from a single table together so that
only the
indexes need to be accessed. This approach saves a trip back to the table.
Syntax
Example
In this query, the optimizer will merge the year_idx and state_idx indexes and will
not need
to access the test2 table
The INDEX_COMBINE hint is used to specify multiple bitmap indexes when you want the
optimizer to use all indexes that you specify.
Syntax
Example
The INDEX_ASC hint currently does exactly the same thing as the INDEX hint. Since
indexes are
already scanned in ascending order, this does nothing more than the current INDEX
hint.
Oracle does not guarantee that indexes will be scanned in ascending order in the
future, but this hint will guarantee that an index will be scanned in ascending
order.
Syntax
Example
The INDEX_DESC hint causes indexes to be scanned in descending order (of their
indexed value
or order), which is the opposite of the INDEX and INDEX_ASC hints.
This hint is overridden when the query has multiple tables, because the index needs
to be used in the normal ascending
order to be joined to the other table in the query.
Syntax
Example
The INDEX_FFS hint indicates a fast full scan of the index should be performed.
This hint
accesses only the index and not the corresponding table. The fast full scan of the
index will be
used only if all of the information that the query needs to retrieve is in the
index. This hint can
give great performance gains, especially when the table has a large number of
columns.
Syntax
Example
The INDEX_FFS hint will be used only if the deptno_idx index contains both the
deptno and
empno columns as a part of it. The NO_INDEX_FFS has the same syntax, but this hint
tells the
optimizer not to perform fast full index scans of the specified indexes
The INDEX_FFS processes only the index and does not take the result
and access the table. All columns that are used and retrieved by the
query must be contained in the index.\
The ORDERED hint causes tables to be accessed in a particular order, based on the
order of the
tables in the FROM clause of the query, which is often referred to as the driving
order for a query.
Before cost-based optimization, the last table in the FROM clause was the driving
table in queries
however, using the ORDERED hint causes the first table in the FROM clause to be the
driver
Syntax
Example
If both tables (emp and dept) have been analyzed (using the cost-based optimizer)
and there
are no indexes on either table, the emp table is accessed first and the dept table
is accessed
second. There are a lot of possible variations (covered in the next two chapters)
that cause this to
work differently.
Example
If all three tables (emp, dept, and orders) have been analyzed and there are no
indexes on
any of the tables, the emp table would be accessed first and then joined to the
dept table, which
would be accessed second. The result would be joined with the orders table, which
is accessed
last
Syntax
select /*+ LEADING (table1) */ column1, �
Example
If all three tables (emp, dept, and orders) have been analyzed and there are no
indexes on
any of the tables, the DEPT table would be accessed first (driving the query). The
optimizer would
figure out the rest (probably accessing the intersection table EMP next).
The NO_EXPAND hint is used to keep the optimizer from �going off the deep end� when
it
is evaluating IN-lists that are combined with an OR. It disallows the optimizer
from using OR
expansion. Without the NO_EXPAND hint, the optimizer may create a very long explain
plan.
Syntax
Example
I have used the NO_EXPAND hint and was able to get performance that was almost 50
times
faster than without the hint.
The DRIVING_SITE hint is identical to the ORDERED hint, except this hint is for
processing data
by driving it from a particular database. The table specified in the hint will be
the driving site that
will be used to process the actual join.
Syntax
Example
Oracle normally would retrieve the rows from the remote site and join them at the
local site
if this hint was not specified. Since the �empno = 7747� limits the query greatly,
we would rather
pass the small number of rows from the emp table to the remote site instead of
pulling an entire
dept table department back to our local site to process.
Limiting the rows that are retrieved from a remote site can also be achieved by
creating a
view locally for the remote table. The local view should have the WHERE clause that
will be
used, so that the view will limit the rows returned from the remote database before
they are sent
back to the local database. I have personally tuned queries from hours to seconds
using this method.
TIP
The DRIVING_SITE hint is extremely powerful, as it will potentially
limit the amount of information that will be processed over your
network. The table specified with the DRIVING_SITE hint will be the
location for the join to be processed
Syntax
Example
The USE_MERGE hint in this query causes the orders table to be joined in a sort-
merge join to the
returned row source resulting from the join of the emp and dept tables
TIP
In a join of three or more tables, the USE_MERGE hint causes the
table(s) specified in the hint to be sort-merge joined with the resulting
row set from a join of the other tables in the join.
The USE_NL (use nested loops) hint is usually the fastest way to return a single
row (response
time); thus, it may be slower at returning all the rows. This hint causes a
statement to be
processed using nested loops, which takes the first matching row from one table
based on the
result from another table. This is the opposite of a merge join, which retrieves
rows that match
the conditions from each table and then merges them together.
Syntax
Example
The USE_NL hint causes the optimizer to take the resulting rows returned from the
emp table
and process them with the matching rows from the dept table (the specified nested
loop table).
The first row that matches from the dept table can be returned to the user
immediately (as in a
web-based application),
The USE_NL hint usually provides the best response time (first row
comes back faster) for smaller result sets; whereas the USE_MERGE
hint usually provides the best throughput when the USE_HASH hint
can�t be used.
The NO_USE_NL hint uses the same syntax, but instructs the optimizer not to use
nested
loops joins, but to use a different join execution plan. A related hint,
USE_NL_WITH_INDEX,
takes two parameters�the name of the inner table for the join along with the name
of the index
to use when performing the join.
The USE_HASH hint is usually the fastest way to join many rows together from
multiple tables if
you have adequate memory for this operation. The USE_HASH <hint or method> is
similar to the
nested loops where one result of one table is looped through the result from the
joined table.
You
must have a large enough HASH_AREA_SIZE or PGA_AGGREGATE_TARGET for
this to work properly; otherwise, the operation will occur on disk.
Syntax
Example
The USE_HASH hint causes the optimizer to take the rows returned from the emp table
and
process them with the matching rows from the dept table (the specified hash table),
which are
hashed into memory. The first row that matches from the dept table can be returned
to the user
immediately, as opposed to waiting until all matching rows are found. There are
cases where
the optimizer will override this hint
The NO_USE_HASH hint has a similar syntax but instructs the optimizer to not use
hash joins when
selecting execution paths for a query. The optimizer will instead use other join
methods such
as nested loops or merge joins.
The PUSH_SUBQ hint can lead to dramatic performance gains (an increase of over 100
times in
performance) when used in the appropriate situation
This hint cannot be used when the query uses a merge join and cannot
be used with remote tables. Moving the subquery to be part of the main query (when
possible)
can lead to the same gains when the tables are driven in the correct order
(accessing the former
subquery table first).
Syntax
This query processes the subquery to be used by the outer query at its earliest
possible time.
The PARALLEL hint causes the optimizer to break a query into pieces (the degree of
parallelism)
and process each piece with a different process. The degree of parallelism is
applied to each
parallelizable operation of a SQL statement.
Syntax
The degree is the number of pieces into which the query is broken.
Example
Example
Example
If a table is created with a parallel degree set, the table will use that degree
for all full table scan
queries. However, you may also �turn off� the use of parallel operations in any one
given query
on a table that has been specified to use parallel operations using the NO_PARALLEL
hint.
Syntax
Example
The APPEND hint improves the performance of INSERTs, but with a potential cost in
terms of
space. The APPEND hint does not check to see if there is space within currently
used blocks for
inserts, but instead appends the data into new blocks.
Syntax
Example
The NOAPPEND hint is used to override the default for the PARALLEL inserts (the
default, of
course, is APPEND). The NOAPPEND hint is the opposite of the APPEND hint and checks
for
free space within current blocks before using new ones.
Syntax
Example
The CACHE hint causes a full table scan to be cached (pinned) into memory, so
future users
accessing the same table find it in memory instead of going to disk. This creates
one potentially
large problem. If the table is very large, it is taking up an enormous amount of
memory (data block
buffer cache space in particular). For small lookup tables, however, this is an
excellent option to
use. Tables can be created with the CACHE option to be cached the first time they
are accessed.
Syntax
Example
Syntax
Example
Example
In this example, the table is not cached despite the ALTER statement and is put on
the Least
Recently Used (LRU) list.
The CLUSTER hint is used only for clusters. A cluster is usually created when
tables are joined
so often that it is faster to create an object containing information about the
joined tables that
is accessed most often. A cluster is identical to denormalizing a table or group of
tables. The
CLUSTER hint forces the use of the cluster. If hashing is used for the cluster (see
the next section),
the HASH hint should be considered. I have not had much luck with using clusters
and gaining
performance.
Syntax
Syntax
Example
The CURSOR_SHARING_EXACT hint is used to ensure that literals in SQL statements are
not
replaced with bind variables. This hint can be used to correct any minor issues
when you don�t
want to use cursor sharing even though instance-level CURSOR_SHARING parameter is
set to
either FORCE or SIMILAR.
Syntax
Example
The QB_NAME hint is used to assign a name to a query block within a statement. You
can then
assign a hint elsewhere in the statement that references the query block. For
example, if you have
a query that contains a subquery, you can assign a query block name to the subquery
and then
provide the hint at the outermost query level. If two or more query blocks are
given the same
QB_NAME value, the optimizer will ignore the hints
========================================= USE_NL_WITH_INDEX
=============================
USE_NL_WITH_INDEX The USE_NL hint instructs the optimizer to use a nested loops
join with the specified table as the non-driving table (or as the inner table that
is looped
through with the result of the driving table). The USE_NL_WITH_INDEX hint allows
you
to also specify the index that is used during the access. However, the optimizer
must be
able to use that index with at least one join.
Select /*+ USE_NL_WITH_INDEX (table index1, index2,...) */
======================================= INDEX_SS
=================================
INDEX_SS The INDEX_SS hint instructs the optimizer to use the �skip scan� option
for
an index on the specified table. A skip scan is where in a concatenated index
Oracle
skips the first column of the index and uses the rest of the index. This hint works
well
with a two-part concatenated index where you often use both parts but infrequently
need only the second part (at times you don�t have any condition for the first
part). You
need to specify both the table and the index.
INDEX_SS_ASC The INDEX_SS_ASC hint is the same as the INDEX_SS hint, but this
could change in a future version of Oracle.
INDEX_SS_DESC The INDEX_SS_DESC hint uses the same syntax as the INDEX_SS
hint but instructs the optimizer to scan the index skip scan in descending order.