The application developer and end users know more about the data and how it is used than the optimizer does. Oracle provides a method known as HINTS to enable you to tell the optimizer the method to use for the SQL statement. Oracle recommends that HINTS not be used as the main method of controlling the optimization for SQL statements. Instead, the SQL statement should be appropriately rewritten for better performance.
You can use hints to specify:
· The optimization approach for a SQL statement
· The goal of the cost-based approach for a SQL statement
· The access path for a table accessed by the statement
· The join order for a join statement
· A join operation in a join statement
A SQL statement can have only one comment containing HINTS. The HINT must be placed after the SELECT, UPDATE, or DELETE keyword in the SQL statement. It should be preceded by /*+ and followed by */.
An alternate approach is to precede the HINT with --+. If multiple HINTS are used, they must be separated by spaces.
To show the format the SELECT statement only will be used, but the format is identical for all three commands.
SELECT /*+ hint or text */ Comment method
statement body
-- or --
SELECT --+ hint or text Dash and Plus sign method
statement body Let's look at an example of the use of hints. In the following example we'll force a full table scan on TKP_EXAMPLE (assuming TKP_EXAMPLE holds the values DEFAULT_TABLESPACE and OWNER):
SELECT /*+ FULL(TKP_EXAMPLE) */
USERNAME,
DEFAULT_TABLESPACE,
TABLESPACE_NAME, TABLE_NAME
FROM
TKP_EXAMPLE, TKP_EXAMPLE2
WHERE
USERNAME NOT IN ('SYS','SYSTEM') AND
DEFAULT_TABLESPACE = TABLESPACE_NAME AND
OWNER = USERNAME;
Notes about HINTS usage:
· If HINTS are incorrectly specified, Oracle will treat the HINT as a comment and will ignore it during SQL statement optimization. You will NOT receive an error message.
· If multiple HINTS exist, Oracle will ignore those with syntax errors but will use those that are correctly included in the statement.
· If any of the HINTS provide conflicting optimization requests, Oracle will not choose between them, and conflicting HINTS will be ignored.
· The optimizer recognizes hints only when using the cost-based approach. If you include a hint (except the RULE hint) in a statement block, the optimizer automatically uses the cost-based approach.
Hints have been organized into the following areas:
Optimizer Hints
Table Access Hints
Hints that affect which optimizer to use and it's behavior:
Hint |
Meaning |
ALL_ROWS |
/*+ ALL_ROWS */ Uses the Cost Based Optimizer if tables or indexes are analyzed. You should set this option if you have a database that is used predominantly for batch processing such as a Data Warehouse |
FIRST_ROWS |
/*+ FIRST_ROWS */ Uses the Cost Based Optimizer if tables or indexes are analyzed. You should set this option if you have a database that is used predominantly for OLTP processing. |
CHOOSE |
/*+ CHOOSE */ If any of the tables or indexes in the statement are analyzed, use the Cost Based Optimizer otherwise use the Rule Based |
RULE |
/*+ RULE */ Use the rule based optimizer for this statement |
Notes:
· RULE, CHOOSE, ALL_ROWS and FIRST_ROWS can be applied at the instance level using the INIT.ora OPTIMIZER_MODE parameter. If set in the INIT.ora, the setting will apply for all SQL statements. The INIT.ora is usually the preferred method to apply the hints unless one particular statement ran well under the Rule Based and is performing unacceptably using the Cost Based.
· The CHOOSE and RULE HINTS specify whether the CBO or the RBO should be used. Correctly specified HINTS will override the optimizer mode specified. If an optimization approach is specified, that approach will be used regardless of the initialization parameter setting for OPTIMIZER_MODE or the session setting for OPTIMIZER_GOAL. Even if statistics are present for one table and the HINT specifies CHOOSE, the optimizer will use the CBO. If no statistics are available, the optimizer will use the RBO. The use of the RULE HINT will cause the optimizer to ignore any other HINTS specified.
· Both the ALL_ROWS and the FIRST_ROWS use the CBO. If no statistics are available, the optimizer will use whatever storage information is available. The ANALYZE command should be used to provide statistics before using either the ALL_ROWS or the FIRST_ROWS HINT. If a HINT specifying an access path or join operation is also specified, it will be given precedence over the ALL_ROWS and FIRST_ROWS HINTS.
· The ALL_ROWS HINT concentrates on the best throughput with the minimum total resource consumption. FIRST_ROWS optimizes with the goal of the best response time with the minimum resource usage necessary to return the first row. The FIRST_ROWS HINT will be ignored for DELETE and UPDATE statements. Because the following statements require that all rows be accessed before any results are returned, the FIRST_ROWS HINT will be ignored if the SQL statement contains:
· Set operators (UNION, UNION ALL, INTERSECT, MINUS)
· The GROUP BY clause
· The FOR UPDATE clause
· Group functions
· The DISTINCT operator
If the described access method requires an index that does not exist, the HINT will be ignored. The table must be specified in the HINT the same as it is in the SQL statement. If an alias is used for the table, the table specified in the HINT must use the table alias instead of the table name. You cannot use the schema name for the table, even if the table is fully qualified in the FROM clause.
Hints that determine how to access a table:
Hint |
Meaning |
AND_EQUAL |
/*+ AND_EQUAL(table [index1 index2...]) */ Used to join single column indexes. You must specify at least 2 indexes. |
APPEND |
INSERT /*+ APPEND */ INTO table…causes the data being inserted to be placed at the end of the table. It does not use free space in the earlier blocks of the table. New with Oracle8. |
CACHE |
/*+ CACHE(table [table...]) */ Places blocks read into the most recently used end of the buffer cache which will retain the data in the buffer cache longer. |
CLUSTER |
/*+ CLUSTER(TABLE) */ Uses a cluster scan. Clusters store each child related to a parent in the same physical address. |
DRIVING_SITE |
/*+ DRIVING_SITE(TABLE [TABLE] ..) */ Forces query execution to be done at a different site. |
FULL |
/*+ FULL(TABLE) */ Tells Oracle to perform a full table scan on the table, even if there is an index in place. If you have the degree of parallelism set, it may also cause the table to be read using parallel query processors. |
HASH |
/*+ HASH(table) */ Uses a hash scan to access the specified table. |
HASH_AJ |
/*+ HASH_AJ */ Uses a hash anti-join to speed up NOT IN. New in Oracle7.3 and later. |
HASH_SJ |
/*+ HASH_SJ */ Uses a hash semi-join to speed up EXISTS. New in Oracle8.1. |
INDEX |
/*+ INDEX(table [index1 index2...]) */ Informs the optimizer to use a specific index on the specified table. |
INDEX_ASC |
/*+ INDEX_ASC(table [index1 index2...]) */ Informs the optimizer to use a specific index on the specified table. |
INDEX_COMBINE |
/*+ INDEX_COMBINE(table [index1 index2...]) */ Informs the optimizer to use a specific index on the specified table. New in Oracle8. Used for bitmap indexes. |
INDEX_DESC |
/*+ INDEX_DESC(table [index1 index2...]) */ Informs the optimizer to use a specific index on the specified table. |
INDEX_FFS |
/*+ INDEX_FFS(table [index1 index2...]) */ Informs the optimizer to perform a fast full index scan instead of a full table scan. It is faster than a normal index scan. New with Oracle8. |
INDEX_JOIN |
/*+ INDEX_JOIN(table [index1 index2...]) */ Informs the optimizer to use an index join as the access path. New with Oracle8.1. |
MERGE |
/*+ MERGE (table) */ Merge a view on a per-query basis. |
MERGE_AJ |
/*+ MERGE_AJ */ Causes NOT IN to be processed using a Merge Join, is often significantly faster than standard NOT processing. |
MERGE_SJ |
/*+ MERGE_SJ */ Transforms a correlated EXISTS subquery into a merge semi-join to access the specified table. |
NOAPPEND |
INSERT /*+ NOAPPEND */ INTO table…overrides APPEND, which is used by default with parallel inserts. New with Oracle8. |
NOCACHE |
/*+ NOCACHE(table [table ...]) */ Places the data into the least recently used end of the buffer cache, which is standard behavior. |
NO_EXPAND |
/*+ NO_EXPAND */ Prevents the cost-based optimizer from considering OR-expansion for queries having OR conditions or INLISTS in the WHERE clause. |
NO_INDEX |
/*+ NO_INDEX(table [index1 index2...]) */ Explicitly disallows a set of indexes for the specified table. |
NO_MERGE |
/*+ NO_MERGE(table) */ Causes Oracle not to merge views specified in the FROM clause. New with Oracle8. |
NOPARALLEL |
/*+ NOPARALLEL (table [table...]) */ Overrides the degree of parallelism against a table to run in non parallel mode. |
NOPARALLEL_INDEX |
/*+ NOPARALLEL_INDEX (table [index...]) */ Overrides a PARALLEL attribute setting on an index. |
NO_PUSH_JOIN_PRED |
/*+ NO_PUSH_JOIN_PRED(table) */ Prevents pushing a join predicate into the view. New with Oracle8.1. |
NOREWRITE |
/*+ NOREWRITE */ Disables query rewrite for the query block. New with Oracle8.1. |
ORDERED |
/*+ ORDERED */ Causes the SQL to be driven by the tables in the order left to right. |
ORDERED_PREDICATES |
/*+ ORDERED_PREDICATES */ Forces the optimizer to preserve the order of predicate evaluation. New with Oracle8.1. |
PARALLEL |
/*+ PARALLEL(table [,integer1 | ,DEFAULT] [,integer2 | ,DEFAULT]) */ Integer1 sets the number of parallel processors to scan the table and integer 2 sets the number per parallel server. |
PARALLEL_INDEX |
/*+ PARALLEL_INDEX (table [index ...] [,int1 | ,DEFAULT] [,int2 | ,DEFAULT])*/ Will use parallel query processes for fast full index scans for indexes which have PARALLEL set. Table specifies the name or alias of the table associated with the index to be scanned. index specifies an index on which an index scan is to be performed (optional). New in Oracle8. |
PQ_DISTRIBUTE |
/*+ PQ_DISTRIBUTE (table [,] outer_dist,inner_dist) */ Improves parallel join operations. Table is the name or alias of a table to be used as the inner table of a join. outer_dist is the distribution for the outer table and inner_dist is the distribution for the inner table. New with Oracle8.1. |
PUSH_JOIN_PRED |
/*+ PUSH_JOIN_PRED(table) */ Forces pushing a join predicate into the view. New with Oracle8.1. |
PUSH_SUBQ |
/*+ PUSH_SUBQ */ Place this hint in a non merged subquery if the subquery performs little processing. |
REWRITE |
/*+ REWRITE(view [view1 view2...]) */ Use with or without a view list to select the materialized view to be used. New with Oracle8.1. |
ROWID |
/*+ ROWID(TABLE) */ Uses a table scan by rowid. |
STAR |
/*+ STAR */ Causes Oracle to merge the reference tables together and join them to the central table using a nested loop. New with Oracle7.3. |
STAR_TRANSFORMATION |
/*+ STAR_TRANSFORMATION */ Causes Oracle to use a star query. It does not always use cartesian product of the reference tables, unlike the STAR hint. New with Oracle8. |
USE_CONCAT |
/*+ USE_CONCAT */ Causes all ORs in the statement to be transferred to UNION ALLs. |
USE_HASH |
/*+ USE_HASH(table [table] ..) */ Tables are joined to the row resulting from using a hash join. New in Oracle8. |
USE_NL |
/*+ USE_NL(table [table]…..) */ Select a row from one row and then returns the associated row from another table using an index. Use for OLTP. |
USE_MERGE |
/*+ USE_MERGE(table [table]…..) */ Will sort each table and merge the rows together. Use for batch processing. |
[Source] Knowledge Xpert for PL/SQL
'Database&WAS > Oracle' 카테고리의 다른 글
[Oracle] COALESCE() 함수 (0) | 2011.06.27 |
---|---|
[Oracle] NULLIF() 함수 (0) | 2011.06.27 |
[Oracle] SUM() 함수 (0) | 2011.06.23 |
HINTs #2 - [Oracle] (0) | 2011.03.16 |
Hint 요약 - [Oracle] (0) | 2011.03.16 |