Sunday, November 7, 2010

Using Database Hints

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 */ as seen in this example:

/*+ FULL(a) */

An alternate approach is to precede the HINT with --+. If multiple HINTS are used, they must be separated by spaces.

Here is an example of a statement using a hint of the first type:

SELECT /*+ FULL(a) */ *
FROM EMP a
WHERE empno > 1;

Note in this case that we are using the FULL hint, which indicates to Oracle that a full tablescan should occur on the EMP table. Note too that we have aliased the hint, which is a good practice but we could have used the table name as well. The other hint form could have been used in this manner:

SELECT --+ FULL(emp)
*
FROM EMP a
WHERE empno > 1;

Insights into 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 and Their Meanings

Hints

Meanings

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

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

If any of the tables or indexes in the statement are analyzed, use the Cost Based Optimizer otherwise use the Rule Based.

RULE

Use the rule based optimizer for this statement.

AND_EQUAL

Used to join single column indexes. You must specify at least 2 indexes.

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. This is new with Oracle8.

CACHE

Places blocks read into the most recently used end of the buffer cache which will retain the data in the buffer cache longer.

CLUSTER

Uses a cluster scan. Clusters store each child related to a parent in the same physical address.

CURSOR_SHARING_EXACT

Disables cursor sharing if it is enabled.

DRIVING_SITE

Forces query execution to be done at a different site.

DYNAMIC_SAMPLING

Allows you to control dynamic sampling.

EXPAND_GSET_TO_UNION

Used for queries containing grouping sets (such as queries with GROUP BY GROUPING SET or GROUP BY ROLLUP). The hint forces a query to be transformed into a corresponding query with UNION ALL of individual groupings.

FACT

Denotes that the hinted table is a fact table when the transformation is a star transformation.

FULL

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

Uses a hash scan to access the specified table.

HASH_AJ

Uses a hash anti-join to speed up NOT IN.

HASH_SJ

Uses a hash semi-join to speed up EXISTS.

INDEX

Informs the optimizer to use a specific index on the specified table.

INDEX_ASC

Informs the optimizer to use a specific index on the specified table.

INDEX_COMBINE

Informs the optimizer to use a specific index on the specified table. Used for bitmap indexes.

INDEX_DESC

Informs the optimizer to use a specific index on the specified table.

INDEX_FFS

Informs the optimizer to perform a fast full index scan instead of a full table scan. It is faster than a normal index scan.

INDEX_JOIN

Informs the optimizer to use an index join as the access path.

LEADING

The LEADING hint causes Oracle to use the specified table as the first table in the join order. An ORDERED hint will override this hint.

MERGE

Merge a view on a per-query basis.

MERGE_AJ

Causes NOT IN to be processed using a Merge Join. It is often significantly faster than standard NOT processing.

MERGE_SJ

Transforms a correlated EXISTS subquery into a merge semi-join to access the specified table.

NOAPPEND

INTO table…overrides APPEND, which is used by default with parallel inserts.

NOCACHE

Places the data into the least recently used end of the buffer cache, which is standard behavior. It also overrides the CACHE setting on a table.

NO_EXPAND

Prevents the cost-based optimizer from considering OR-expansion for queries having OR conditions or INLISTS in the WHERE clause.

NO_FACT

Denotes that the hinted table is not a fact table when the transformation is a star transformation.

NO_INDEX

Explicitly disallows a set of indexes for the specified table.

NO_MERGE

Causes Oracle not to merge views specified in the FROM clause.

NO_PUSH_PRED

Prevents a join predicate from being pushed into the view.

NO_PUSH_SUBQ

Delays evaluation of non-merged subqueries until the last step in the execution plan.

NOPARALLEL

Overrides the degree of parallelism against a table to run in non parallel mode.

NOPARALLEL_INDEX

Overrides a PARALLEL attribute setting on an index.

NO_PUSH_JOIN_PRED

Prevents pushing a join predicate into the view.

NO_UNNEST

Prevents unnesting for specific subquery blocks.

NOREWRITE

Disables query rewrite for the query block.

ORDERED

Causes the SQL to be driven by the tables in the order left to right.

ORDERED_PREDICATES

Causes the order of predicate evaluation to be preserved by the optimizer.

PARALLEL

Sets the number of parallel processors to scan a table.

PARALLEL_INDEX

Will use parallel query processes for fast full index scans for indexes which have PARALLEL set.

PQ_DISTRIBUTE

Improves parallel join operations.

PUSH_JOIN_PRED

Forces pushing a join predicate into the view.

PUSH_PRED

Forces a join predicate to be pushed into the view.

PUSH_SUBQ

Place this hint in a non merged subquery if the subquery performs little processing.

REWRITE

Use with or without a view list to select the materialized view to be used.

ROWID

Uses a table scan by rowid.

STAR

Causes Oracle to merge the reference tables together and join them to the central table using a nested loop

STAR_TRANSFORMATION

Causes Oracle to use a star query. It does not always use cartesian product of the reference tables, unlike the STAR hint.

UNNEST

Merges nested subqueries into the body of the statement that contains them. The optimizr then considers them together as it evaluates access paths and joins.

USE_CONCAT

Causes all ORs in the statement to be transferred to UNION ALLs.

USE_HASH

Tables are joined to the row resulting from using a hash join.

USE_NL

Selects a row from one row and then returns the associated row from another table using an index. Use for OLTP.

USE_MERGE

Will sort each table and merge the rows together. Use for batch processing.


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.

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.


Source:

http://www.toadworld.com/KNOWLEDGE/KnowledgeXpertforOracle/tabid/648/TopicID/HNTS/Default.aspx

Oracle SQL Hints

ORACLE SQL HINTS


Optimizer - SQL Hints

Sometimes, the optimizer needs some suggestions in order to make the best possible choice, even when armed with good statistics. These suggestions can be given to the optimizer in the form of hints in your SQL statements. While hints give direction to the optimizer, the optimizer is under no obligation to follow them every time.


Hints are specified by enclosing the hint in a comment in the query. Multiple hints can be contained in the comment. The comment must follow the SELECT, INSERT, UPDATE, or DELETE keyword and must contain a plus sign, '+' at the start. If the hint is not specified properly, then it will be ignored with no errors or warnings from the optimizer. A hint is specified as follows:

SELECT /*+ hint [text] [hint [text]] … */ ….

Or

/*+ hint */

/*+ hint(argument) */

/*+ hint(argument-1 argument-2) */


An example of a hint is as follows:

SELECT /*+ INDEX( e emp_pk) */

FROM emp e

WHERE empid IN (1001, 1002);

In the above example, the INDEX hint is used to suggest a specific index to the optimizer. Normally, a table name is denoted to define which table to use that index, but in this example the table was aliased in the FROM clause, therefore the hint must use the table's alias. If the table was aliased in the FROM clause, and the table name was used in the hint, the hint would be ignored.


All hints except /*+ rule */ cause the CBO to be used. Therefore, it is good practice to analyze the underlying tables if hints are used (or the query is fully hinted.

There should be no schema names in hints. Hints must use aliases if alias names are used for table names. So the following is wrong:

select /*+ index(scott.emp ix_emp) */ from scott.emp emp_alias

better:

select /*+ index(emp_alias ix_emp) */ ... from scott.emp emp_alias


Why to Use Hints

It is a perfect valid question to ask why hints should be used. Oracle comes with an optimizer that promises to optimize aquery's execution plan. When this optimizer is really doing a good job, no hints should be required at all.

Sometimes, however, the characteristics of the data in the database are changing rapidly, so that the optimizer (or more accuratly, its statistics) are out of date. In this case, a hint could help.

It must also be noted, that Oracle allows to lock the statistics when they look ideal which should make the hints meaningless again.

Hint categories

Hints can be categorized as follows:

  1. Hints for Optimization Approaches and Goals,
  2. Hints for Access Paths, Hints for Query Transformations,
  3. Hints for Join Orders,
  4. Hints for Join Operations,
  5. Hints for Parallel Execution,
  6. Miscellaneous Hints


1. Optimizer Mode Hints

The optimizer mode for the SQL statement can be specified as a hint. This overrides the instance and session settings for the optimizer mode. The optimizer hints are as follows:

ALL_ROWS

  • return all rows as fast as possible
  • One of the hints that 'invokes' the Cost based optimizer
  • ALL_ROWS is usually used for batch processing or data warehousing systems.


FIRST_ROWS(n)

  • return the first n rows as fast as possible, where n is 1, 10, 100, or 1000.
  • One of the hints that 'invokes' the Cost based optimizer
  • FIRST_ROWS is usually used for OLTP systems.


RULE

  • use to denote Rule Based Optimization. Not valid in Oracle 10g.
  • The RULE hint should be considered deprecated as it is dropped from Oracle9i2.

CHOOSE

  • use to denote Cost Based Optimization. Not valid in Oracle 10g.
  • One of the hints that 'invokes' the Cost based optimizer
  • This hint lets the server choose (between ALL_ROWS and FIRST_ROWS, based on statistics gathered

2. Access Path Hints

There are many ways to access data in a table. You can perform a full table scan or access the data using an index on the table. If using an index, you can use it in ascending mode or descending mode. The access path hints are:

CLUSTER

  • Performs a nested loop by the cluster index of one of the tables.

HASH

  • Hashes one table (full scan) and creates a hash index for that table. Then hashes other table and uses hash index to find corresponding records. Therefore not suitable for < or > join conditions.

ROWID

  • Retrieves the row by rowid

INDEX

  • Specifying that index index_name should be used on table tab_name: /*+ index (tab_name index_name) */
  • Specifying that the index should be used the the CBOthinks is most suitable. (Not always a good choice).
  • Starting with Oracle 10g, the index hint can be described: /*+ index(my_tab my_tab(col_1, col_2)) */. Using the index on my_tab that starts with the columns col_1 and col_2.

INDEX_COMBINE

AND_EQUAL
The AND_EQUAL hint explicitly chooses an execution plan that uses an access path that merges the scans on several single-column indexes

FULL suggests a full table scan

NO_INDEX suggests not to use an index

INDEX_ASC suggests to use an index in ascending mode

INDEX_DESC suggests to use an index in descending mode

INDEX_JOIN suggests to use an index join access method

INDEX_FFS suggests to use an index full fast scan

NO_INDEX_FFS suggests not to use an index full fast scan

INDEX_SS suggests to use an index skip scan. Available only in Oracle 10g.

INDEX_SS_ASC suggests to use an index skip scan in ascending mode. Available only in Oracle 10g.

INDEX_SS_DESC suggests to use an index skip scan in descending mode. Available only in Oracle 10g.

NO_INDEX_SS suggests not to use an index skip scan. Available only in Oracle 10g.

3. Join Hints

There are many methods used to join two tables together. The join hints are:

  • USE_NL Use a Nested Loop join method. Can specify the inner table.
  • NO_USE_NL Do not use a Nested Loop join method. Available only in Oracle 10g.
  • USE_NL_WITH_INDEX Use a Nested Loop join method with an index. Available only in Oracle 10g.
  • USE_MERGE Use a Sort Merge join method. Can specify the inner table.
  • NO_USE_MERGE Do not use a Sort Merge join method. Available only in Oracle 10g.
  • USE_HASH Use a Hash join method. Can specify the inner table
  • NO_USE_HASH Do not use the Hash join method. Available only in Oracle 10g.

4. Parallel Hints

There are a number of hints used in parallel processing of queries. Parallel queries use multiple processors on the database server to obtain results faster. The paralle hints are:

  • PARALLEL(n) Suggest to perform the operation in parallel. The degree of parallelization, n, can be specified.
  • NO_PARALLEL Suggest to not perform the query in parallel. This overrides the parallel specification for a table.
  • PARALLEL_INDEX(n) Suggest to parallelize the index range scan. The degree of parallelization, n, can be specified.
  • NO_PARALLEL_INDEX Suggest to not parallelize the index range scan.

5. Miscellaneous Hints

The miscellaneous hints are:

  • APPEND
Enables Direct Path insert mode so that data is appended to the end of the table.
If a table or an index is specified with nologging, this hint applied with an insert statement produces a direct path insert which reduces generation of redo


Undocumented hints:


Note: The above information helped me to optimize queries on Transaction tables which will be updated every second with several new records. The following are the sources which provided me information to publish this post.

Source:

  1. http://www.toadworld.com/KNOWLEDGE/KnowledgeXpertforOracle/tabid/648/TopicID/OTOC91/Default.aspx
  2. http://www.adp-gmbh.ch/ora/sql/hints/index.html
  3. http://download.oracle.com/docs/cd/A97630_01/server.920/a96533/toc.htm