Você está na página 1de 10

Oracle SQL Hints Tuning

Oracle Tips by Burleson Consulting


Using Hints to tune SQL

Mike Ault

There are many Oracle hints available to the developer for use in tuning SQL statements that are embedded in PL/SQL. You should first get the explain plan of your SQL and determine what changes can be done to make the code operate without using hints if possible. However, Oracle hints such as ORDERED, LEADING, INDEX, FULL, and the various AJ and SJ Oracle hints can tame a wild optimizer and give you optimal performance. Oracle hints are enclosed within comments to the SQL commands DELETE, SELECT or UPDATE or are designated by two dashes and a plus sign. To show the format the SELECT statement only will be used, but the format is identical for all three commands.

SELECT body

/*+ hint --or-- text */

statement

-- or -SELECT --+ hint --or-- text statement body

Where:

/*, */ - These are the comment delimiters for multi-line comments -- - This is the comment delimiter for a single line comment (not usually used for hints) + - This tells Oracle a hint follows, it must come immediately after the /* hint - This is one of the allowed hints text - This is the comment text

Oracle Hint

Meaning

+ ALL_ROWS CHOOSE FIRST_ROWS RULE Access Method Oracle Hints: CLUSTER(table) FULL(table)

Must be immediately after comment indicator, tells Oracle this is a list of hints. Use the cost based approach for best throughput. Default, if statistics are available will use cost, if not, rule. Use the cost based approach for best response time. Use rules based approach; this cancels any other hints specified for this statement.

This tells Oracle to do a cluster scan to access the table. This tells the optimizer to do a full scan of the specified table. Tells Oracle to explicitly choose the hash access method for HASH(table) the table. HASH_AJ(table) Transforms a NOT IN subquery to a hash anti-join. ROWID(table) Forces a rowid scan of the specified table. Forces an index scan of the specified table using the specified index(s). If a list of indexes is specified, the optimizer chooses INDEX(table [index]) the one with the lowest cost. If no index is specified then the optimizer chooses the available index for the table with the lowest cost. Same as INDEX only performs an ascending search of the INDEX_ASC (table [index]) index chosen, this is functionally identical to the INDEX statement. Same as INDEX except performs a descending search. If INDEX_DESC(table [index]) more than one table is accessed, this is ignored. Combines the bitmapped indexes on the table if the cost INDEX_COMBINE(table index) shows that to do so would give better performance. INDEX_FFS(table index) Perform a fast full index scan rather than a table scan. MERGE_AJ (table) Transforms a NOT IN subquery into a merge anti-join. AND_EQUAL(table index index This hint causes a merge on several single column indexes. [index index index]) Two must be specified, five can be. Transforms a NOT IN subquery into a NL anti-join (nested NL_AJ loop). Inserted into the EXISTS subquery; This converts the subquery into a special type of hash join between t1 and t2 HASH_SJ(t1, t2) that preserves the semantics of the subquery. That is, even if there is more than one matching row in t2 for a row in t1, the row in t1 is returned only once. Inserted into the EXISTS subquery; This converts the subquery into a special type of merge join between t1 and t2 MERGE_SJ (t1, t2) that preserves the semantics of the subquery. That is, even if there is more than one matching row in t2 for a row in t1, the row in t1 is returned only once.

NL_SJ

Inserted into the EXISTS subquery; This converts the subquery into a special type of nested loop join between t1 and t2 that preserves the semantics of the subquery. That is, even if there is more than one matching row in t2 for a row in t1, the row in t1 is returned only once.

Oracle Hints for join orders and transformations: ORDERED STAR STAR_TRANSFORMATION FACT(table) NO_FACT(table) PUSH_SUBQ REWRITE(mview) This hint forces tables to be joined in the order specified. If you know table X has fewer rows, then ordering it first may speed execution in a join. Forces the largest table to be joined last using a nested loops join on the index. Makes the optimizer use the best plan in which a start transformation is used. When performing a star transformation use the specified table as a fact table. When performing a star transformation do not use the specified table as a fact table. This causes nonmerged subqueries to be evaluated at the earliest possible point in the execution plan. If possible forces the query to use the specified materialized view, if no materialized view is specified, the system chooses what it calculates is the appropriate view. Turns off query rewrite for the statement, use it for when data returned must be concurrent and can't come from a materialized view. Forces combined OR conditions and IN processing in the WHERE clause to be transformed into a compound query using the UNIONALL set operator. This causes Oracle to join each specified table with another row source without a sort-merge join. Prevents OR and IN processing expansion.

NOREWRITE

USE_CONCAT NO_MERGE (table)

NO_EXPAND Oracle Hints for Join Operations: USE_HASH (table) This causes Oracle to join each specified table with another row source with a hash join. This operation forces a nested loop using the specified table USE_NL(table) as the controlling table. This operation forces a sort-merge-join operation of the USE_MERGE(table,[table, - ]) specified tables. The hint forces query execution to be done at a different site DRIVING_SITE than that selected by Oracle. This hint can be used with either rule-based or cost-based optimization.

LEADING(table) Oracle Hints for Parallel Operations: [NO]APPEND NOPARALLEL (table PARALLEL(table, instances) PARALLEL_INDEX Other Oracle Hints: CACHE

The hint causes Oracle to use the specified table as the first table in the join order.

This specifies that data is to be or not to be appended to the end of a file rather than into existing free space. Use only with INSERT commands. This specifies the operation is not to be done in parallel. This specifies the operation is to be done in parallel. Allows parallelization of a fast full index scan on any index. Specifies that the blocks retrieved for the table in the hint are placed at the most recently used end of the LRU list when the table is full table scanned. Specifies that the blocks retrieved for the table in the hint are placed at the least recently used end of the LRU list when the table is full table scanned. For insert operations will append (or not append) data at the HWM of table. Turns on the UNNEST_SUBQUERY option for statement if UNNEST_SUBQUERY parameter is set to FALSE. Turns off the UNNEST_SUBQUERY option for statement if UNNEST_SUBQUERY parameter is set to TRUE. Pushes the join predicate into the view.

NOCACHE [NO]APPEND UNNEST NO_UNNEST PUSH_PRED

As you can see, a dilemma with a stubborn index can be easily solved using FULL or NO_INDEX Oracle hints. You must know the application to be tuned. The DBA can provide guidance to developers but in all but the smallest development projects, it will be nearly impossible for a DBA to know everything about each application. It is clear that responsibility for application tuning rests solely on the developer's shoulders with help and guidance from the DBA.

Using Global Hints


While Oracle hints normally refer to table in the query it is possible to specify a hint for a table within a view through the use of what are known as Oracle GLOBAL HINTS. This is done using the Oracle global hint syntax. Any table hint can be transformed into an Oracle global hint. The syntax is:

/*+ hint(view_name.table_in_view) */

For example:

/*+ full(sales_totals_vw.s_customer)*/

If the view is an inline view, place an alias on it and then use the alias to reference the inline view in the Oracle global hint.
ALL_ROWS AND_EQUAL ANTIJOIN APPEND BITMAP BUFFER BYPASS_RECURSIVE_CHECK BYPASS_UJVC CACHE CACHE_CB CACHE_TEMP_TABLE CARDINALITY CHOOSE CIV_GB COLLECTIONS_GET_REFS CPU_COSTING CUBE_GB CURSOR_SHARING_EXACT DEREF_NO_REWRITE DML_UPDATE DOMAIN_INDEX_NO_SORT DOMAIN_INDEX_SORT DRIVING_SITE DYNAMIC_SAMPLING DYNAMIC_SAMPLING_EST_CDN EXPAND_GSET_TO_UNION FACT FIRST_ROWS FORCE_SAMPLE_BLOCK FULL GBY_CONC_ROLLUP GLOBAL_TABLE_HINTS HASH HASH_AJ INDEX_SS_ASC INDEX_SS_DESC INLINE LEADING LIKE_EXPAND LOCAL_INDEXESMATERIALIZE MERGE MERGE_AJ MERGE_SJ MV_MERGE NESTED_TABLE_GET_REFS NESTED_TABLE_SET_REFS NESTED_TABLE_SET_SETID NL_AJ NL_SJ NO_ACCESS NO_BUFFER NO_EXPAND NO_EXPAND_GSET_TO_UNION NO_FACT NO_FILTERING NO_INDEX NO_MERGE NO_MONITORING NO_ORDER_ROLLUPS NO_PRUNE_GSETS NO_PUSH_PRED NO_PUSH_SUBQ NO_QKN_BUFF NO_SEMIJOIN NO_STATS_GSETS NO_UNNEST NOAPPEND NOCACHE PARALLEL PARALLEL_INDEX PIV_GB PIV_SSF PQ_DISTRIBUTE PQ_MAP PQ_NOMAP PUSH_PRED PUSH_SUBQ REMOTE_MAPPED RESTORE_AS_INTERVALS REWRITE RULE SAVE_AS_INTERVALS SCN_ASCENDING SELECTIVITY SEMIJOIN SEMIJOIN_DRIVER SKIP_EXT_OPTIMIZER SQLLDR STAR STAR_TRANSFORMATION SWAP_JOIN_INPUTS SYS_DL_CURSOR SYS_PARALLEL_TXN SYS_RID_ORDER TIV_GB TIV_SSF UNNEST USE_ANTI USE_CONCAT USE_HASH USE_MERGE USE_NL

HASH_SJ HWM_BROKERED IGNORE_ON_CLAUSE IGNORE_WHERE_CLAUSE INDEX_ASC INDEX_COMBINE INDEX_DESC INDEX_FFS INDEX_JOIN INDEX_RRS INDEX_SS

NOCPU_COSTING NOPARALLEL NOPARALLEL_INDEX NOREWRITE OR_EXPAND ORDERED ORDERED_PREDICATES OVERFLOW_NOMOVE

USE_SEMI USE_TTT_FOR_GSETS

Used separately, hints and views are terrific tools for Oracle tuning. But used together, they can cause severe performance problems. Lets look at what hints, views, and materialized views can do for you. Then, we'll consider when and how to use them.

Hints
Hints are compiler directives that change the execution plan for SQL statements. Of course, if the Oracle cost-based optimizer (CBO) and rule-based optimizer (RBO) always made optimal execution plans, hints would not be necessary. There are two classes of hints:

General mode hintsThis class of hints changes the overall execution mode for Oracle queries. These hints include /*+ rule */ and /*+ first_rows */. Detailed directive hintsThis class of hints directs specific access paths, such as the use of a hash join over a nested loop join, /*+ use_hash */, and the use of a specific index to access a table.

In sum, hints are a necessary and useful tool for tuning SQL statements.

Views
An Oracle view is the encapsulation of a complex query into a single pseudotable that behaves like a single table. For example, here we create a view: create or replace view cust_view as select customer_name, order_nbr, item_desc

from customer c, order o, item i, where c.cust_nbr = o.cust_nbr and o_item_nbr = i.item_nbr; The pseudotable in the following query hides the complexity of the underlying query and has no effect on the performance of the underlying SQL: select * from cust_view where cust_nbr = 123; In this example, every time the cust_view is queried, Oracle will join the three tables at runtime. Since views don't improve performance, why use them? Most Oracle shops that employ views do so for end-user queries or for queries where they want to hide complexity and ensure uniform join methods.

Materialized views
Oracles solution to improving performance of standard views is the materialized view. When you create a material view, it prejoins all of the tables in a complex query. Since all of the query joins have been done, running SQL against the materialized view will be far faster than with a standard view. However, materialized views have some shortcomings:

More storage is requiredSince the materialized view actually performs the query, extra disk space is required to store the result table. Materialized views become staleFrom the moment the materialized view is created, the view may become out-of-date. To periodically refresh a materialized view, you can use a mechanism that's similar to an Oracle snapshot.

* LEADING */ Hint specifies the set of tables to be used as the prefix in the execution plan.

The "leading" hint is ignored if the tables specified cannot be joined first in the order specified If you specify two or more conflicting LEADING hints all of them are ignored The ORDERED hint overrides all LEADING hints

/* ORDERED */ Hint Oracle joins tables in the order in which they appear in the FROM clause

The optimizer normally chooses the order in which to join the tables, but it's time-consuming and wrong if you have bad CBO stats (especially histograms) You may want to specify the "ordered" hint if you know something about the number of rows selected from each table that the optimizer does not

The Oracle 10g documentation notes the difference between the "ordered" and "leading" hints: The LEADING hint causes Oracle to use the specified table as the first table in the join order. If you specify two or more LEADING hints on different tables, then all of them are ignored. If you specify the ORDERED hint, then it overrides all LEADING hints. ndexing NULL table column values for fast SQL performance
Oracle Tips by Burleson Consulting September 21, 2003 - Revised January 1, 2007 One problem with all relational databases is having the optional ability to index on a NULL column. By default, relational databases ignore NULL values (because the relational model says that NULL means "not present"). Hence, Oracle indexes will not include NULL values. For example, this index definition would not index on "open positions", new employee positions that are stored with a NULL employee name: create index emp_ename_idx on emp (ename) ; Whenever a SQL query asks for the open position employee slots "where ename is NULL", there will be no index entries for NULLS in emp_name_idx and Oracle would perform an unnecessary large-table full-table scan.
Execution Plan --------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=6) 1 0 TABLE ACCESS (FULL) OF 'EMP' (Cost=1 Card=1 Bytes=6)

To get around the optimization of SQL queries that choose NULL column values, we can create a function-based index using the null value built-in SQL function to index only on the NULL columns. Note that the "null value" (NVL) function replaces NULL values with the character string "null', a real value that can participate in an index:

-- create an FBI on ename column with NULL values create index emp_null_ename_idx on emp (nvl(ename,'null')); analyze index emp_null_ename_idx compute statistics;

You can also do this techniques with NULL numeric values. This syntax replaces NULL values with a zero:
-- create an FBI on emp_nbr column with NULL values create index emp_null_emp_nbr_idx on emp (nvl(ename,o)); analyze index emp_null_ename_idx compute statistics;

Now we can use the index and greatly improve the speed of any queries that require access to the NULL columns. Note that we must make one of two changes: 1- Add a hint to force the index 2 - Change the WHERE predicate to match the function Here is an example of using an index on NULL column values:
-- insert a NULL row insert into emp (empno) values (999); set autotrace traceonly explain;

-- test the index access (change predicate to use FBI) select /*+ index(emp_null_ename_idx) */ ename from emp e where nvl(ename,'null') = 'null' ;

Reader Comments:
I was reading "Indexing NULL table column values for fast SQL performance" article, where you have mentioned that if the column is having null values (of very less amount) and you want to select where column is null then to use the index, create function based index and changed your query to use that index. I think, it can be done without changing query as well......

SQL> select count(1) from t where n is null; COUNT(1) ---------334 Execution Plan --------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=1 Bytes=3) 1 0 SORT (AGGREGATE) 2 1 TABLE ACCESS (FULL) OF 'T' (Cost=3 Card=334 Bytes=1002) SQL> create index tind on t(n, 1); ----> here 1 is just any arbitary value. Index created. SQL> exec dbms_stats.gather_table_stats(user,'t',cascade=>true); PL/SQL procedure successfully completed. SQL> select count(1) from t where n is null; COUNT(1) ---------334 Execution Plan ---------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=4) 1 0 SORT (AGGREGATE) 2 1 INDEX (RANGE SCAN) OF 'TIND' (NON-UNIQUE) (Cost=2 Card=3 34 Bytes=1336)

Sandeep Redkar

Você também pode gostar