Intoduction to oracle tuning
| Article Index |
|---|
| 1. Do this before you start individual SQL statement tuning |
| 2. Oracle SQL tuning goals |
| 3. A strategic plan for Oracle SQL tuning |
| 4. Tips for writing more efficient SQL |
It is goog idea to start with system-level SQL tuning, else later changes might undo your tuned execution plans. Optimize the server kernel - 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.
1. Do this before you start individual SQL statement tuning
ALWAYS start with system-level SQL tuning, else later changes might undo your tuned execution plans.
Optimize the server kernel - 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 - Always collect and store optimizer statistics to allow the optimizer to learn more about the distribution of your data to take intelligent execution plans.
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 - Create missing indexes and missing materialized views on the recommendations of 10g SQLAccess advisor.
11g Note: Oracle 11g SQL Performance Analyzer (SPA), is designed to speed up the SQL tuning process. Once you create a workload (called a SQL Tuning Set, or STS), Oracle will repeatedly execute the workload, 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.
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.
2. Oracle SQL tuning goals
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 unnecessary I/O. If query returns less than 40% of the table rows, it needs tuning. The common tuning remedy is adding indexes(b-tree, bitmapped or function-based).
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, the small table can be cached by forcing it into the KEEP pool.
Verify optimal index usage- When using the rule-based optimizer. 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- Materialized views pre-join tables and pre-summarize data.
3. A strategic plan for Oracle SQL tuning
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
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 tatement.
Step 3 Tune the SQL statement
For those SQL statements that possess a nonoptimal 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
A hint is a directive that is added to the SQL statement to modify the access path for a SQL query. 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.
4. Tips for writing more efficient SQL
Some general rules for writing efficient SQL in Oracle regardless of the optimizer that is chosen.
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- 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.
1 |
SELECT book_key FROM book |
Below we combine the outer join with a NULL test in the WHERE clause without using a sub-query, giving a faster execution plan.
1 |
SELECT b.book_key FROM book b, sales s |
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:
1 |
WHERE salary*5 > :myvalue |
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:
1 |
WHERE cust_nbr = "123" |
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 table aliases - Always use table aliases when referencing columns.
Last Updated (Tuesday, 24 November 2009 10:48)



