uning
individual Oracle SQL statements
The acronym SQL stands for
Structured Query Language. SQL is an industry standard database query language
that was adopted in the mid-1980s. It should not be confused with commercial
products such as Microsoft SQL Server or open source products such as MySQL,
both of which use the acronym as part of the title of their products.
Do
this before you start individual SQL statement tuning
This broad-brush approach can save
thousands of hours of tedious SQL tuning because you can hundreds of queries at
once. Remember, you MUST do this first, else later changes to the
optimizer parameters or statistics may un-tune your SQL.
Remember, you must ALWAYS start with
system-level SQL tuning, else later changes might undo your tuned execution
plans:
- Optimize the server kernel - You must always tune your disk and network I/O
subsystem (RAID, DASD bandwidth, network) to optimize the I/O time,
network packet size and dispatching frequency.
- Adjusting your optimizer statistics - You must always collect and store optimizer
statistics to allow the optimizer to learn more about the distribution of
your data to take more intelligent execution plans. Also, histograms
can hypercharge SQL in cases of determining optimal table join order, and
when making access decisions on skewed WHERE clause predicates.
- Adjust optimizer parameters - Optimizer optimizer_mode, optimizer_index_caching,
optimizer_index_cost_adj.
- Optimize your instance - Your choice of db_block_size, db_cache_size,
and OS parameters (db_file_multiblock_read_count, cpu_count, &c), can
influence SQL performance.
- Tune your SQL Access workload with physical indexes and materialized views - Just as the 10g SQLAccess advisor recommends missing indexes and missing materialized views, you should always optimize your SQL workload with indexes, especially function-based indexes, a Godsend for SQL tuning.
11g Note: The Oracle 11g SQL Performance Analyzer (SPA), is
primarily designed to speed up the holistic SQL tuning process.
Once you create a workload (called a SQL Tuning Set, or STS), Oracle will repeatedly execute the workload, using sophisticated predictive models (using a regression testing approach) to accurately identify the salient changes to SQL execution plans, based on your environmental changes. Using SPA, we can predict the impact of system changes on a workload, and we can forecast changes in response times for SQL after making any change, like parameter changes, schema changes, hardware changes, OS changes, or Oracle upgrades. For details, see the book Oracle 11g New Features.
Once you create a workload (called a SQL Tuning Set, or STS), Oracle will repeatedly execute the workload, using sophisticated predictive models (using a regression testing approach) to accurately identify the salient changes to SQL execution plans, based on your environmental changes. Using SPA, we can predict the impact of system changes on a workload, and we can forecast changes in response times for SQL after making any change, like parameter changes, schema changes, hardware changes, OS changes, or Oracle upgrades. For details, see the book Oracle 11g New Features.
Once the environment, instance, and
objects have been tuned, the Oracle administrator can focus on what is probably
the single most important aspect of tuning an Oracle database: tuning the
individual SQL statements. In this final article in my series on Oracle tuning,
I will share some general guidelines for tuning individual SQL statements to
improve Oracle performance.
Oracle SQL tuning goals
Oracle SQL tuning is a phenomenally
complex subject. Entire books have been written about the nuances of Oracle SQL
tuning; however, there are some general guidelines that every Oracle DBA
follows in order to improve the performance of their systems. Again, see the
book "Oracle Tuning: The Definitive Reference", for complete details.
The goals of SQL tuning focus on improving the execution plan to fetch the rows with the smallest number of database "touches" (LIO buffer gets and PIO physical reads).
The goals of SQL tuning focus on improving the execution plan to fetch the rows with the smallest number of database "touches" (LIO buffer gets and PIO physical reads).
- Remove unnecessary large-table full-table scans—Unnecessary full-table scans cause a huge amount of
unnecessary I/O and can drag-down an entire database. The tuning expert
first evaluates the SQL based on the number of rows returned by the query.
The most common tuning remedy for unnecessary full-table scans is adding
indexes. Standard b-tree indexes can be added to tables, and bitmapped and
function-based indexes can also eliminate full-table scans. In some cases,
an unnecessary full-table scan can be forced to use an index by adding an
index hint to the SQL statement.
- Cache small-table full-table scans—In cases where a full-table scan is the fastest access
method, the administrator should ensure that a dedicated data buffer is
available for the rows. In Oracle8 and beyond, a small table can be
cached by forcing it into the KEEP pool.
- Verify optimal index usage—Oracle sometimes has a choice of indexes, and the tuning
professional must examine each index and ensure that Oracle is using the
proper index.
- Materialize your aggregations and summaries for static tables - One features of the Oracle 10g SQLAccess advisor is recommendations for new indexes and suggestions for materialized views. Materialized views pre-join tables and pre-summarize data, a real silver bullet for data mart reporting databases where the data is only updated daily. Again, see the book "Oracle Tuning: The Definitive Reference", for complete details on SQL tuning with materialized views.
These are the goals of SQL tuning in
a nutshell. However, they are deceptively simple, and to effectively meet them,
we need to have a through understanding of the internals of Oracle SQL. Let's
begin with an overview of the Oracle SQL optimizers.
Oracle SQL optimizers
One of the first things the Oracle
DBA looks at is the default optimizer mode for the database. The Oracle
initialization parameters offer many cost-based optimizer modes as well as the
deprecated yet useful rule-based hint:
The cost-based optimizer uses
“statistics” that are collected from the table using the “analyze table”
command. Oracle uses these metrics about the tables in order to intelligently
determine the most efficient way of servicing the SQL query. It is important to
recognize that in many cases, the cost-based optimizer may not make the proper
decision in terms of the speed of the query. The cost-based optimizer is
constantly being improved, but there are still many cases in which the
rule-based optimizer will result in faster Oracle queries.
Prior to Oracle 10g, Oracle's
default optimizer mode was called “choose.” In the choose optimizer mode,
Oracle will execute the rule-based optimizer if there are no statistics present
for the table; it will execute the cost-based optimizer if statistics are
present. The danger with using the choose optimizer mode is that problems can
occur in cases where one Oracle table in a complex query has statistics and the
other tables do not.
Starting in Oracle 10g, the default
optimizer mode is all_rows, favoring full-table scans over index access.
The all_rows optimizer mode is designed to minimize computing resources and it
favors full-table scans. Index access (first_rows_n) adds
additional I/O overhead, but they return rows faster, back to the originating
query:
Full-table scans touch all data blocks
Hence, many OLTP shops will choose first_rows,
first_rows_100 or first_rows_10, asking Oracle to use indexes to reduce block
touches:
Index scans return rows fast by doing additional I/O
Note: Staring in Oracle9i release 2, the Oracle performance tuning
guide says that the first_rows optimizer mode has been deprecated and to
use first_rows_n instead.
When only some tables contain CBO
statistics, Oracle will use the cost-based optimization and estimate statistics
for the other tables in the query at runtime. This can cause significant
slowdown in the performance of the individual query.
In sum, the Oracle database
administrator will always try changing the optimizer mode for queries as the
very first step in Oracle tuning. The foremost tenet of Oracle SQL tuning is
avoiding the dreaded full-table scan. One of the hallmarks of an inefficient
SQL statement is the failure of the SQL statement to use all of the indexes
that are present within the Oracle database in order to speed up the query.
Of course, there are times when a full-table scan is appropriate for a query, such as when you are doing aggregate operations such as a sum or an average, and the majority of the rows within the Oracle table must be read to get the query results. The task of the SQL tuning expert is to evaluate each full-table scan and see if the performance can be improved by adding an index.
Of course, there are times when a full-table scan is appropriate for a query, such as when you are doing aggregate operations such as a sum or an average, and the majority of the rows within the Oracle table must be read to get the query results. The task of the SQL tuning expert is to evaluate each full-table scan and see if the performance can be improved by adding an index.
In most Oracle systems, a SQL
statement will be retrieving only a small subset of the rows within the table.
The Oracle optimizers are programmed to check for indexes and to use them
whenever possible to avoid excessive I/O. However, if the formulation of a
query is inefficient, the cost-based optimizer becomes confused about the best
access path to the data, and the cost-based optimizer will sometimes choose to
do a full-table scan against the table. Again, the general rule is for the
Oracle database administrator to interrogate the SQL and always look for
full-table scans.
For the full story, see my book
"Oracle Tuning: The Definitive Reference" for details on choosing the right optimizer mode.
A strategic plan for Oracle SQL
tuning
Many people ask where they should start when tuning Oracle SQL. Tuning Oracle SQL is like fishing. You must first fish in the Oracle library cache to extract SQL statements and rank the statements by their amount of activity.
Step 1—Identify high-impact SQL
The SQL statements will be ranked according the number of executions and will be tuned in this order. The executions column of the v$sqlarea view and the stats$sql_summary or the dba_hist_sql_summary table can be used to locate the most frequently used SQL. Note that we can display SQL statements by:
Many people ask where they should start when tuning Oracle SQL. Tuning Oracle SQL is like fishing. You must first fish in the Oracle library cache to extract SQL statements and rank the statements by their amount of activity.
Step 1—Identify high-impact SQL
The SQL statements will be ranked according the number of executions and will be tuned in this order. The executions column of the v$sqlarea view and the stats$sql_summary or the dba_hist_sql_summary table can be used to locate the most frequently used SQL. Note that we can display SQL statements by:
- Rows processed—Queries
that process a large number of rows will have high I/O and may also have
impact on the TEMP tablespace.
- Buffer gets—High
buffer gets may indicate a resource-intensive query.
- Disk reads—High
disk reads indicate a query that is causing excessive I/O.
- Memory KB—The
memory allocation of a SQL statement is useful for identifying statements
that are doing in-memory table joins.
- CPU secs—This
identifies the SQL statements that use the most processor resources.
- Sorts—Sorts
can be a huge slowdown, especially if they’re being done on a disk in the
TEMP tablespace.
- Executions—The more frequently executed SQL statements should be tuned first, since they will have the greatest impact on overall performance.
Step 2—Determine the execution plan for SQL
As each SQL statement is identified, it will be “explained” to determine its existing execution plan. There are a host of third-party tools on the market that show the execution plan for SQL statements. The most common way of determining the execution plan for a SQL statement is to use Oracle's explain plan utility. By using explain plan, the Oracle DBA can ask Oracle to parse the statement and display the execution class path without actually executing the SQL statement.
To see the output of an explain plan, you must first create a “plan table.” Oracle provides a script in $ORACLE_HOME/rdbms/admin called utlxplan.sql. Execute utlxplan.sql and create a public synonym for the plan_table:
sqlplus > @utlxplan
Table created.
sqlplus > create public synonym plan_table for sys.plan_table;
Synonym created.
Most relational databases use an
explain utility that takes the SQL statement as input, runs the SQL optimizer,
and outputs the access path information into a plan_table, which can then be
interrogated to see the access methods. Listing 1 runs a complex query against
a database.
EXPLAIN PLAN SET STATEMENT_ID = 'test1' FOR
SET STATEMENT_ID = 'RUN1'
INTO plan_table
FOR
SELECT 'T'||plansnet.terr_code,
'P'||detplan.pac1
|| detplan.pac2 || detplan.pac3, 'P1',
sum(plansnet.ytd_d_ly_tm),
sum(plansnet.ytd_d_ty_tm),
sum(plansnet.jan_d_ly),
sum(plansnet.jan_d_ty),
FROM plansnet, detplan
WHERE
plansnet.mgc = detplan.mktgpm
AND
detplan.pac1 in
('N33','192','195','201','BAI',
'P51','Q27','180','181','183','184','186','188',
'198','204','207','209','211')
GROUP BY 'T'||plansnet.terr_code, 'P'||detplan.pac1 ||
detplan.pac2 || detplan.pac3;
This syntax is piped into the SQL
optimizer, which will analyze the query and store the plan information in a row
in the plan table identified by RUN1. Please note that the query will not
execute; it will only create the internal access information in the plan table.
The plan tables contains the following fields:
- operation—The
type of access being performed. Usually table access, table merge, sort,
or index operation
- options—Modifiers
to the operation, specifying a full table, a range table, or a join
- object_name—The
name of the table being used by the query component
- Process ID—The
identifier for the query component
- Parent_ID—The parent of the query component. Note that several query components may have the same parent.
Now that the plan_table has been
created and populated, you may interrogate it to see your output by running the
following query in Listing 2.
plan.sql - displays contents of the explain plan table
SET PAGES 9999;
SELECT lpad(' ',2*(level-1))||operation operation,
options,
object_name,
position
FROM plan_table
START WITH id=0
AND
statement_id = 'RUN1'
CONNECT BY prior id = parent_id
AND
statement_id
= 'RUN1';
Listing 3 shows the output from the
plan table shown in Listing 1. This is the execution plan for the statement and
shows the steps and the order in which they will be executed.
SQL> @list_explain_plan
OPERATION
-------------------------------------------------------------------------------------
OPTIONS
OBJECT_NAME
POSITION
------------------------------
-------------------------------------------------------
SELECT STATEMENT
SORT
GROUP
BY
1
CONCATENATION
1
NESTED
LOOPS
1
TABLE ACCESS
FULL
PLANSNET
1
TABLE ACCESS BY ROWID
DETPLAN
2
INDEX
RANGE SCAN DETPLAN_INDEX5
1
NESTED LOOPS
From this output, we can see the dreaded TABLE ACCESS FULL on the PLANSNET table. To diagnose the reason for this full-table scan, we return to the SQL and look for any plansnet columns in the WHERE clause. There, we see that the plansnet column called “mgc” is being used as a join column in the query, indicating that an index is necessary on plansnet.mgc to alleviate the full-table scan.
While the plan table is useful for determining the access path to the data, it does not tell the entire story. The configuration of the data is also a consideration. The SQL optimizer is aware of the number of rows in each table (the cardinality) and the presence of indexes on fields, but it is not aware of data distribution factors such as the number of expected rows returned from each query component.
Step 3—Tune the SQL statement
For those SQL statements that possess a sub-optimal execution plan, the SQL will be tuned by one of the following methods:
For those SQL statements that possess a sub-optimal execution plan, the SQL will be tuned by one of the following methods:
- Adding SQL “hints” to modify the execution plan
- Re-write SQL with Global Temporary Tables
- Rewriting the SQL in PL/SQL. For certain queries this can result in more than a 20x performance improvement. The SQL would be replaced with a call to a PL/SQL package that contained a stored procedure to perform the query.
Using hints to tune Oracle SQL
Among the most common tools for tuning SQL statements are hints. A hint is a directive that is added to the SQL statement to modify the access path for a SQL query.
Among the most common tools for tuning SQL statements are hints. A hint is a directive that is added to the SQL statement to modify the access path for a SQL query.
Troubleshooting tip! For testing, you can quickly test the effect of
another optimizer parameter value at the query level without using an “alter
session” command, using the new opt_param
SQL hint:
select /*+ opt_param('optimizer_mode','first_rows_10')
*/ col1, col2 . . .
select /*+
opt_param('optimizer_index_cost_adj',20) */ col1, col2 . .
Oracle publishes many dozens of SQL
hints, and hints become increasingly more complicated through the various
releases of Oracle and on into Oracle.
Note: Hints are only used for
de-bugging and you should adjust your optimizer statistics to make the CBO
replicate the hinted SQL. Let’s look at the most common hints to improve
tuning:
- Mode hints: first_rows_10, first_rows_100
- Oracle leading and
ordered hints
Also see how to tune table join order with histograms
- Dynamic sampling: dynamic_sampling
- Oracle SQL undocumented tuning hints - Guru's only
- The cardinality hint
· Self-order the table joins - If you
find that Oracle is joining the tables together in a sub-optimal order, you can
use the ORDERED hint to force the tables to be joined in the order that they
appear in the FROM clause. See
·
Try a first_rows_n hint. Oracle has two cost-based optimizer
modes, first_rows_n and all_rows. The first_rows mode will
execute to begin returning rows as soon as possible, whereas the all_rows mode
is designed to optimize the resources on the entire query before returning
rows.
SELECT /*+ first_rows */
A case study in SQL tuning
One of the historic problems with SQL involves formulating SQL queries. Simple queries can be written in many different ways, each variant of the query producing the same result—but with widely different access methods and query speeds.
For example, a simple query such as “What students received an A last semester?” can be written in three ways, as shown in below, each returning an identical result.
A standard join:
SELECT *
FROM STUDENT, REGISTRATION
WHERE
STUDENT.student_id =
REGISTRATION.student_id
AND
REGISTRATION.grade = 'A';
A nested query:
SELECT *
FROM STUDENT
WHERE
student_id =
(SELECT student_id
FROM REGISTRATION
WHERE
grade = 'A'
);
A correlated subquery:
SELECT *
FROM STUDENT
WHERE
0 <
(SELECT count(*)
FROM REGISTRATION
WHERE
grade = 'A'
AND
student_id =
STUDENT.student_id
);
Let’s wind up with a review of the
basic components of a SQL query and see how to optimize a query for remote
execution.
Tips for writing more efficient SQL
Space doesn’t permit me to discuss every detail of Oracle tuning, but I can share some general rules for writing efficient SQL in Oracle regardless of the optimizer that is chosen. These rules may seem simplistic but following them in a diligent manner will generally relieve more than half of the SQL tuning problems that are experienced:
Tips for writing more efficient SQL
Space doesn’t permit me to discuss every detail of Oracle tuning, but I can share some general rules for writing efficient SQL in Oracle regardless of the optimizer that is chosen. These rules may seem simplistic but following them in a diligent manner will generally relieve more than half of the SQL tuning problems that are experienced:
- Rewrite complex subqueries with temporary tables - Oracle created the global temporary table (GTT) and
the SQL WITH operator to help divide-and-conquer complex SQL sub-queries
(especially those with with WHERE clause subqueries, SELECT clause scalar
subqueries and FROM clause in-line views). Tuning SQL with temporary tables (and materializations in the WITH clause) can result
in amazing performance improvements.
- Use minus instead of EXISTS subqueries - Some say that
using the minus operator instead of NOT IN and NOT Exists will result in a
faster execution plan.
- Use SQL analytic functions - The Oracle analytic functions can do multiple
aggregations (e.g. rollup by cube) with a single pass through the tables,
making them very fast for reporting SQL.
- Re-write NOT EXISTS and NOT EXISTS subqueries as outer joins - In many cases of NOT queries (but ONLY where a column is defined as NULL), you can re-write the uncorrelated subqueries into outer joins with IS NULL tests. Note that this is a non-correlated sub-query, but it could be re-written as an outer join.
select book_key from book
where
book_key NOT IN (select book_key from sales);
where
book_key NOT IN (select book_key from sales);
Below we combine the outer join with
a NULL test in the WHERE clause without using a sub-query, giving a faster
execution plan.
select b.book_key from book b, sales
s
where
b.book_key = s.book_key(+)
and
s.book_key IS NULL;
where
b.book_key = s.book_key(+)
and
s.book_key IS NULL;
- Index your NULL values - If you have SQL that frequently tests for NULL,
consider creating an index on NULL values. To get around the optimization of SQL queries
that choose NULL column values (i.e. where emp_name IS NULL), we
can create a function-based index using the null value built-in SQL
function to index only on the NULL columns.
- Leave column names alone - Never do a calculation on an indexed column unless you have a matching function-based index (a.k.a. FBI). Better yet, re-design the schema so that common where clause predicates do not need transformation with a BIF:
where
salary*5 >
:myvalue
where substr(ssn,7,4) = "1234"
where to_char(mydate,mon) = "january"
where substr(ssn,7,4) = "1234"
where to_char(mydate,mon) = "january"
- Avoid the use of NOT IN or HAVING. Instead, a NOT EXISTS subquery may run faster (when
appropriate).
- Avoid the LIKE predicate = Always replace a "like" with an equality,
when appropriate.
- Never mix data types - If a WHERE clause column predicate is numeric, do not to use quotes. For char index columns, always use quotes. There are mixed data type predicates:
where cust_nbr = "123"
where substr(ssn,7,4) = 1234
where substr(ssn,7,4) = 1234
- Use decode and case -
Performing complex aggregations with the “decode” or "case"
functions can minimize the number of times a table has to be selected.
- Don't fear full-table scans - Not all OLTP queries are optimal when they uses
indexes. If your query will return a large percentage of the table
rows, a full-table scan may be faster than an index scan. This depends on many factors, including your configuration (values
for db_file_multiblock_read_count, db_block_size), query
parallelism and the number of table/index blocks in the buffer cache.
- Use those aliases - Always use table aliases when referencing columns.
ORACLE HINTS
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
/*+ hint --or-- text */
statement body
-- 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
|
+
|
Must be immediately after comment
indicator, tells Oracle this is a list of hints.
|
ALL_ROWS
|
Use the cost based approach for
best throughput.
|
CHOOSE
|
Default, if statistics are
available will use cost, if not, rule.
|
FIRST_ROWS
|
Use the cost based approach for
best response time.
|
RULE
|
Use rules based approach; this
cancels any other hints specified for this statement.
|
Access Method Oracle Hints:
|
|
CLUSTER(table)
|
This tells Oracle to do a cluster
scan to access the table.
|
FULL(table)
|
This tells the optimizer to do a
full scan of the specified table.
|
HASH(table)
|
Tells Oracle to explicitly choose
the hash access method for 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.
|
INDEX(table [index])
|
Forces an index scan of the
specified table using the specified index(s). If a list of indexes is
specified, the optimizer chooses 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.
|
INDEX_ASC (table [index])
|
Same as INDEX only performs an
ascending search of the index chosen, this is functionally identical to the
INDEX statement.
|
INDEX_DESC(table [index])
|
Same as INDEX except performs a
descending search. If more than one table is accessed, this is ignored.
|
INDEX_COMBINE(table index)
|
Combines the bitmapped indexes on
the table if the cost 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 [index
index index])
|
This hint causes a merge on
several single column indexes. Two must be specified, five can be.
|
NL_AJ
|
Transforms a NOT IN subquery into
a NL anti-join (nested loop).
|
HASH_SJ(t1, t2)
|
Inserted into the EXISTS subquery;
This converts the subquery into a special type of hash 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.
|
MERGE_SJ (t1, t2)
|
Inserted into the EXISTS subquery;
This converts the subquery into a special type of merge 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.
|
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
|
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.
|
STAR
|
Forces the largest table to be
joined last using a nested loops join on the index.
|
STAR_TRANSFORMATION
|
Makes the optimizer use the best
plan in which a start transformation is used.
|
FACT(table)
|
When performing a star
transformation use the specified table as a fact table.
|
NO_FACT(table)
|
When performing a star
transformation do not use the specified table as a fact table.
|
PUSH_SUBQ
|
This causes nonmerged subqueries
to be evaluated at the earliest possible point in the execution plan.
|
REWRITE(mview)
|
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.
|
NOREWRITE
|
Turns off query rewrite for the
statement, use it for when data returned must be concurrent and can't come from a materialized view.
|
USE_CONCAT
|
Forces combined OR conditions and
IN processing in the WHERE clause to be transformed into a compound query
using the UNION ALL set operator.
|
NO_MERGE (table)
|
This causes Oracle to join each
specified table with another row source without a sort-merge join.
|
NO_EXPAND
|
Prevents OR and IN
processing expansion.
|
Oracle Hints for Join Operations:
|
|
USE_HASH (table)
|
This causes Oracle to join each
specified table with another row source with a hash join.
|
USE_NL(table)
|
This operation forces a nested
loop using the specified table as the controlling table.
|
USE_MERGE(table,[table, - ])
|
This operation forces a
sort-merge-join operation of the specified tables.
|
DRIVING_SITE
|
The hint forces query execution to
be done at a different site than that selected by Oracle. This hint can be
used with either rule-based or cost-based optimization.
|
LEADING(table)
|
The hint causes Oracle to use the
specified table as the first table in the join order.
|
Oracle Hints for Parallel
Operations:
|
|
[NO]APPEND
|
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.
|
NOPARALLEL (table
|
This specifies the operation is
not to be done in parallel.
|
PARALLEL(table, instances)
|
This specifies the operation is to
be done in parallel.
|
PARALLEL_INDEX
|
Allows parallelization of a fast
full index scan on any index.
|
Other Oracle Hints:
|
|
CACHE
|
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.
|
NOCACHE
|
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.
|
[NO]APPEND
|
For insert operations will append
(or not append) data at the HWM of table.
|
UNNEST
|
Turns on the UNNEST_SUBQUERY
option for statement if UNNEST_SUBQUERY parameter is set to FALSE.
|
NO_UNNEST
|
Turns off the UNNEST_SUBQUERY
option for statement if UNNEST_SUBQUERY parameter is set to TRUE.
|
PUSH_PRED
|
Pushes the join predicate
into the view.
|
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.
No comments:
Post a Comment