Vous êtes sur la page 1sur 70

Oracle SQL Tuning

Why Tune ?
• To improve response time
• To improve batch throughput
• To ensure scalability
• To reduce system load
• To avoid hardware upgrades
Tuning Techniques
• Re-wording the SQL
• Giving Oracle explicit instructions called Hints
• Creating or changing indexes or clusters
• Changing the table structure
Types of SQL Statements
• Data Definition Language (DDL), used to define the
database structure or schema: CREATE, DROP, ALTER,
TRUNCATE
• Data Manipulation Language (DML), used for
managing data within schema objects: SELECT, INSERT,
UPDATE, DELETE, MERGE/UPSERT
• Data Control Language (DCL), used to control access
to data stored in a database: GRANT, REVOKE, DENY
• Transaction Control Language (TCL), used to manage
the changes made by DML statements: COMMIT,
SAVEPOINT, ROLLBACK
Query Operations
• Subqueries: nested subquery (in the WHERE clause),
inline views (in the FROM clause), in the SELECT clause,
correlated subquery
• Joins: inner, outer, self, equi-joins
• Set: UNION, UNION ALL, MINUS, INTERSECT
• Aggregations: AVG, COUNT, MAX, MIN, SUM
SQL Processing
Create Cursor Allocate memory for cursor

Parse SQL Check syntax and security


Associate program variable

Bind Variables
with SQL
Execute DML statement or

Execute SQL
prepare query to

Query? Fetch rows Retrieve one or more rows

Close Cursor SQL execution ended

Re-execute Re-execute SQL statement


Cursor De-allocate cursor memory

Close Cursor
and discard
What is Parsing?
• It is the process of preparing the SQL statement for
execution
• Process:
» Check that the SQL statement syntactically valid
» Check that the statement is semantically valid
» Check security
» Determine an execution plan
Improving Parse Speed
• The parse phase for statements can be decreased
by efficient use of aliasing. If an alias is not present,
the engine must resolve which tables own the
specified columns. The following is an example:

Bad Statement Good Statement

SELECT first_name, last_name, SELECT e.first_name, e.last_name,


country c.country
FROM employee, countries FROM employee e, countries c
WHERE country_id = id WHERE e.country_id = c.id
AND lastname = 'HALL'; AND e.last_name = 'HALL';
Shared SQL
• It is a cache of recently executed SQL
• Maintained in SQL Area of Shared Pool
• Avoids unnecessary parsing
Bind Variables
• Bind Variables are fixed references to variables contained
elsewhere in the programming language
Why are we talking of Parsing,
Shared SQL and Bind Variables?
• Parsing is expensive
• Excessive parsing can bottleneck the application
• If you are going to re-execute an SQL with different
parameters use bind variables
Advantages of using Bind Variables

• No new cursor is created


• No re-parsing takes place
• If another session executes the same SQL statement, a
match is found in the shared pool
Bind Variables in SQL*Plus
• In SQL*Plus you can use bind variables as follows:

SQL> variable deptno number


SQL> exec :deptno := 10
SQL> select * from emp where deptno = :deptno;
Bind Variables in PL/SQL

• The good news is that every reference to a PL/SQL


variable is in fact a bind variable

create or replace procedure dsal(p_empno in number)


as
begin
update emp
set sal=sal*2
where empno = p_empno;
commit;
end;
Dynamic SQL

• The only time you need to consciously decide to use


bind variables when working with PL/SQL is when using
Dynamic SQL, which allows you to execute a string
containing SQL using the EXECUTE IMMEDIATE
command
Bind Variables in VB, Java and other
applications
• When you put together an SQL statement using Java, or VB,
or whatever, you usually use an API for accessing the
database; ADO in the case of VB, JDBC in the case of Java.
All of these APIs have built-in support for bind variables, and
it's just a case of using this support rather than just
concatenating a string yourself and submitting it to the
database.
• For example, Java has PreparedStatement, which allows
the use of bind variables, and Statement, which uses the
string concatenation approach. If you use the method that
supports bind variables, the API itself passes the bind
variable value to Oracle at runtime, and you just submit your
SQL statement as normal.
Execution Plan

• The combination of the steps Oracle uses to execute


a statement is called an execution plan.
Query Optimization

• It is the process of determining the “optimal” path


to retrieve data
Approaches to Query Optimization

• Rule based
– Based on predefined set of precedence rules (rigid
rules) to figure out which path it will use to access the
database.
– Does not take into account the volume of data
• Cost based
– Takes into account statistical information relating to
volume and distribution of data within tables and
indexes (it uses database information such as table
size, number of rows, key spread, and so forth,
rather than rigid rules).
Goals of Query Optimization (1 of 2)

• RULE
– This specifies that the optimizer is to take the rule based
approach to optimization
• CHOOSE
– This specifies that the optimizer is to use the cost based
approach if any of the table in the SQL statement has
been analyzed.
– If no tables have been analyzed, then use the rule based
approach.
Goals of Query Optimization (2 of 2)

• ALL_ROWS
– This explicitly chooses the cost-based approach to
optimize a statement block with a goal of best
throughput (that is, minimum total resource)
• FIRST_ROWS
– This explicitly chooses the cost-based approach to
optimize a statement block with a goal of best response
time (minimum resource usage to return first row).
Statistics Used for the Cost-Based Approach

• The cost-based approach uses statistics to estimate


the cost of each execution plan.
• These statistics can be generated using the ANALYZE
command, or DBMS_STATS package.
• Using these statistics, the optimizer estimates how much
I/O, CPU time, and memory are required to execute a
SQL statement using a particular execution plan.
ANALYZE Command (1 of 2)
• You can analyze the storage characteristics of tables, indexes, and clusters to
gather statistics which are then stored in the data dictionary.
• The optimizer uses these statistics in a cost-based approach to determine the
most efficient execution plan for the SQL statements you issue. Note that
statistics can be either computed or estimated, depending on the amount of
overhead you are willing to allow for this purpose.
• Queries with many joins are quite sensitive to the accuracy of the statistics.
• Use the COMPUTE option of the ANALYZE command if possible (it may take
quite some time and a large amount of temporary space). If you must use the
ESTIMATE option, sample as large a percentage as possible.
• When you analyze a table, the indexes that are defined on that table are also
analyzed.
ANALYZE Command (2 of 2)

• Syntax:
ANALYZE TABLE <table name> COMPUTE/ESTIMATE
STATISTICS
• The statistics are visible through these data dictionary
views:
– USER_TABLES, ALL_TABLES, and DBA_TABLES
– USER_TAB_COLUMNS, ALL_TAB_COLUMNS, and
DBA_TAB_COLUMNS
How Oracle Optimizes SQL Statements

• Evaluation of expressions and conditions


• Statement transformation
• View merging
• Choice of optimization approaches
• Choice of access paths
• Choice of join orders
• Choice of join operations
How does Oracle access data?

• At the physical level Oracle reads blocks of data. The


smallest amount of data read is a single Oracle block, the
largest is constrained by operating system limits (and
multiblock I/O)
Logical Access Method
• Full Table Scan (FTS) - In a FTS operation, the whole table is read
up to the high water mark (HWM). The HWM marks the last block in
the table that has ever had data written to it. If you have deleted all
the rows then you will still read up to the HWM. Truncate resets the
HWM back to the start of the table.
• Index Lookup (unique & non-unique) - Data is accessed by
looking up key values in an index and returning rowids. A rowid
uniquely identifies an individual row in a particular data block. This
block is read via single block I/O.
• Rowid - This is the quickest access method available Oracle simply
retrieves the block specified and extracts the rows it is interested in.
Most frequently seen in explain plans as Table access by Rowid
What is EXPLAIN PLAN? (1 of 2)

• The EXPLAIN PLAN command displays the execution plan


chosen by the Oracle optimizer for SELECT, UPDATE,
INSERT, and DELETE statements.
• A statement's execution plan is the sequence of operations
that Oracle performs to execute the statement.
• The general syntax of EXPLAIN PLAN is:
explain plan for sql-statement;

• If you do an EXPLAIN PLAN, Oracle will analyze the


statement and fill a special table with the Execution plan for
that statement.
What is EXPLAIN PLAN? (2 of 2)

• You can indicate which table has to be filled with the


following SQL command:
explain plan into table_name for sql-statement;

• If you omit the INTO TABLE_NAME clause, Oracle fills a


table named PLAN_TABLE by default.
• The plan table is the table that Oracle fills when you have it
explain an execution plan for an SQL Statement.
• Oracle ships with the script UTLXPLAN.SQL in
$ORACLE_HOME/rdbms/admin/ directory which creates
this table, named PLAN_TABLE.
Understanding Explain Plan
• Simple explain plan:
Query Plan
-----------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1234 TABLE
ACCESS FULL LARGE [:Q65001] [ANALYZED]
• In this case TABLE ACCESS FULL LARGE is the first operation.
This statement means we are doing a full table scan of table LARGE. The resultant
row source is passed up to the next level of the query for processing (SELECT
STATEMENT)
• [CHOOSE] is an indication of the optimizer_goal for the query.
• To determine the optimizer_goal observe the following
- If cost has value it means CBO is used
SELECT STATEMENT [CHOOSE] Cost=1234

- If cost is blank it mean RBO is used


SELECT STATEMENT [CHOOSE] Cost=
Access Methods in Detail (1 of 3)

• FULL TABLE SCAN Example:


SQL> explain plan for select * from dual;
Query Plan
-----------------------------------------
SELECT STATEMENT [CHOOSE] Cost=
TABLE ACCESS FULL DUAL
Access Methods in Detail (2 of 3)
• INDEX LOOKUP
SQL> explain plan for select empno, ename from emp where empno=7566;
Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1
TABLE ACCESS BY ROWID EMP [ANALYZED]
INDEX UNIQUE SCAN EMP_I1
• Notice the 'TABLE ACCESS BY ROWID' section. This indicates that
the table data is not being accessed via a FTS operation but rather by
a rowid lookup. In this case the rowid has been produced by looking
up values in the index first. The index is being accessed by an
'INDEX UNIQUE SCAN' operation. This is explained below. The index
name in this case is EMP_I1. If all the required data resides in the
index then a table lookup may be unnecessary and all you will see is
an index access with no table access.
Access Methods in Detail (3 of 3)

• In the following example all the columns (empno) are in the


index. Notice that no table access takes place:
SQL> explain plan for select empno from emp where empno=7566;
Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1
INDEX UNIQUE SCAN EMP_I1
• Indexes are presorted so sorting may be unecessary if the
sort order required is the same as the index.
Index Lookup Methods (1 of 5)
• Index Unique Scan - Method for looking up a single key
value via a unique index, which always returns a single
value. You must supply AT LEAST the leading column of
the index to access data via the index. However this may
return > 1 row as the uniqueness will not be guaranteed.
SQL> explain plan for select empno,ename from emp where empno=7566;
Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1
TABLE ACCESS BY ROWID EMP [ANALYZED]
INDEX UNIQUE SCAN EMP_I1
Index Lookup Methods (2 of 5)
• Index Range Scan - Method for accessing multiple column
values You must supply AT LEAST the leading column of
the index to access data via the index, which can be used
for range operations (e.g. > < <> >= <= between).
SQL> explain plan for select empno,ename from emp where empno >
7566 order by empno;
Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1
TABLE ACCESS BY ROWID EMP [ANALYZED]
INDEX RANGE SCAN EMP_I1 [ANALYZED]
Index Lookup Methods (3 of 5)
• Index Full Scan - In certain circumstances it is possible for
the whole index to be scanned as opposed to a range
scan.
--create concatenated index
CREATE INDEX EMP_INDEX ON EMP(EMPNO,ENAME);

SQL> explain plan for select empno, ename from emp order by empno,
ename;
Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=26
INDEX FULL SCAN EMP_INDEX [ANALYZED]
Index Lookup Methods (4 of 5)
• Index Fast Full Scan
empno is PK and index name is pk_emp
SELECT /*+INDEX_FFS(EMP PK_EMP)*/ EMPNO FROM EMP;
Scans all the block in the index. Rows are not returned in
sorted order.
Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1
INDEX FAST FULL SCAN PK_EMP [ANALYZED]
Index Lookup Methods (5 of 5)
• Rowid
This is the quickest access method available Oracle simply
retrieves the block specified and extracts the rows it is
interested in.
SQL> explain plan for select * from dept where rowid = ':x';
Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1
TABLE ACCESS BY ROWID DEPT [ANALYZED]
Common Execute Steps (1 of 5)

Category Operation Option Description


Table Access TABLE ACCESS FULL Implies a full table scan
Paths TABLE ACCESS BY ROWID Access a row by specifying the
ROWID
Index AND-EQUAL Results from one or more index
Operations scans are combined
INDEX UNIQUE SCAN An index lookup which will
return the address of only one
row
INDEX RANGE SCAN An index lookup which will
return the address of more than
one row. Like a non-unique
index
Common Execute Steps (2 of 5)
Category Operation Option Description
Join Operations CONNECT BY A retrieval of rows in a hierarchical
order for a query containing a
CONNECT BY clause.
MERGE JOIN An operation that accepts two sets
of rows, each sorted by a specific
value, combines each row from one
set with the matching rows from the
other, and returns the result.
MERGE JOIN OUTER A merge join operation to perform an
outer join statement.
NESTED LOOPS An operation that accepts two sets
of rows, an outer set and an inner
set. Oracle compares each row of
the outer set with each row of the
inner set and returns those rows that
satisfy a condition.
NESTED LOOPS OUTER A nested loops operation to perform
an outer join statement.
Common Execute Steps (3 of 5)
Category Operation Option Description
Set Operations CONCATENATION An operation that accepts multiple sets
of rows and returns the union-all of the
sets.
INTERSECTION An operation that accepts two sets of
rows and returns the intersection of the
sets, eliminating duplicates.
MINUS An operation that accepts two sets of
rows and returns rows that appear in
the first set but not in the second,
eliminating duplicates.
UNION An operation that accepts two sets of
rows and returns the union of the sets,
eliminating duplicates.
VIEW An operation that performs a view's
query and then returns the resulting
rows to another operation.
Common Execute Steps (4 of 5)
Category Operation Option Description
Miscellaneous FOR UPDATE An operation that retrieves and
locks the rows selected by a
query containing a FOR
UPDATE clause.
FILTER An operation that accepts a set
of rows, eliminates some of
them, and returns the rest.
REMOTE A retrieval of data from a remote
database.
SEQUENCE An operation involving accessing
values of a sequence.
SORT ORDER BY An operation that sorts a set of
rows for a query with an ORDER
BY clause.
Common Execute Steps (5 of 5)
Category Operation Option Description
Aggregation COUNT An operation that counts the
number of rows selected from a
table.
COUNT STOPKEY A count operation where the
number of rows returned is limited
by the ROWNUM expression in the
WHERE clause.
SORT AGGREGATE A retrieval of a single row that is
the result of applying a group
function to a group of selected
rows.
SORT JOIN An operation that sorts a set of
rows before a merge-join operation
SORT UNIQUE An operation that sorts a set of
rows to eliminate duplicates.
SORT GROUP BY An operation that sorts a set of
rows into groups for a query with a
GROUP BY clause.
Influencing Optimizer using HINTS

• Hints are instructions that can be included in the SQL


statement to instruct or “guide” the optimizer.
Some HINTS (1 of 8)
• FULL(table name)
The FULL hint explicitly chooses a full table scan for the
specified table. For example, Oracle performs a full table
scan on the ACCOUNTS table to execute this statement,
even if there is an index on the ACCNO column that is
made available by the condition in the WHERE clause:
SELECT /*+ FULL(a) Don't use the index on ACCNO */ accno,
bal FROM accounts a
WHERE accno = 7086854;
Some HINTS (2 of 8)
• INDEX(table name, index name)
The INDEX hint explicitly chooses an index scan for the specified
table. If this hint specifies a single available index, the optimizer
performs a scan on this index. If this hint specifies a list of
available indexes, the optimizer considers the cost of a scan on
each index in the list and then performs the index scan with the
lowest cost. If this hint specifies no indexes, the optimizer
considers the cost of a scan on each available index on the table
and then performs the index scan with the lowest cost.
SELECT /*+ INDEX(patients, sex_index) Use SEX_INDEX, since there are few
male patients */ name, height, weight
FROM patients
WHERE sex = 'M';
Some HINTS (3 of 8)
• ROWID(table name)
The ROWID hint explicitly chooses a table scan by
ROWID for the specified table
SELECT /*+ROWID(emp) */ FROM emp WHERE rowid >
'AAAAtkAABAAAFNTAAA'
AND empno = 7566;
Some HINTS (4 of 8)
• ORDERED
The ORDERED hint causes Oracle to join tables in the order in
which they appear in the FROM clause. For example, this
statement joins table TAB1 to table TAB2 and then joins the
result to table TAB3:
SELECT /*+ ORDERED */ tab1.col1, tab2.col2, tab3.col3
FROM tab1, tab2, tab3
WHERE tab1.col1 = tab2.col1
AND tab2.col1 = tab3.col1;

• If you omit the ORDERED hint from a SQL statement


performing a join, the optimizer chooses the order in which to
join the tables.
Some HINTS (5 of 8)
• Index Fast Full Scan
The INDEX_FFS will process ONLY the index. All columns
that are used and retrieved by the query MUST be
contained in the index.
SELECT /*+INDEX_FFS(EMPLOYEES EMP_NAME_IX)*/
LAST_NAME FROM EMPLOYEES
WHERE LAST_NAME='KING';
Some HINTS (6 of 8)
• USE_NL
Use nested loop joins when the subset of data between the
two joining tables is small. Because nested loop joins fetch
the data as soon as possible, they are the preferred joins
when either the data doesn't need to be sorted or you need
the queries to return quickly. For the example below,
assume B is having 1000 rows and A is having 100 rows:
SELECT /*+ ORDERED USE_NL(A) */
FROM B, A
Where A.column1 = B.column2;
Some HINTS (7 of 8)
• USE_HASH
This hint is best suited for joining tables that have a large
subset of data. A hash join offers better throughput and is
best suited for sorting and ordering queries. When the size
of the tables is large, the hash table size becomes pretty
large and it requires more CPU and memory. The syntax
for the hint is:
/*+ USE_HASH (table_name) */

• For example:
SELECT /*+ USE_HASH (s i) */ DISTINCT s.srvr_id
FROM servers s, serv_inst i
WHERE s.srvr_id = i.srvr_id;
Some HINTS (8 of 8)
• USE_MERGE
The merge hint requires that both inputs be sorted on the merge
columns, which are defined by the equality (WHERE) clauses of the join
predicate. Because each input is sorted, the merge join operator gets a
row from each input and compares them. For example, for inner join
operations, the rows are returned if they are equal. If they are not equal,
whichever row has the lower value is discarded and another row is
obtained from that input. This process repeats until all rows have been
processed. The syntax for this hint is:
/*+ USE_MERGE(table_name) */
• For example:
SELECT /*+ USE_MERGE (s i) */ DISTINCT s.srvr_id
FROM servers s, serv_inst i
WHERE s.srvr_id = i.srvr_id;
Full Table Scans vs Index Lookups

• If all rows or a large number of rows of a table has to be


accessed then a full table scan is the quickest way of doing
it.
• If a single row or 5% to 10% of the rows in a table has to
be accessed, use indexes.
Avoiding “Accidental” Table Scans

• Sometimes the index may not be used if queries are


framed as:
– Queries involving != (NOT EQUALS) condition
– Searching for NULLS
– Accidentally disabling an index with a function (eg
upper(last_name))
Optimizing Index Lookups

• Where possible optimize a query by including all of the


columns contained in the WHERE clause within a
concatenated index
• Try to maintain the order of the column in the index in the
WHERE clause
• A LIKE ‘SM%’ will benefit from the index whereas a ‘%SM
%’ will not be able to leverage the benefits of an index
Queries Involving OR

• For queries involving OR condition try using the hints


USE_CONCAT, FULL or INDEX
Index merges for queries involving AND

• If Oracle performs an index merge (AND-EQUALS in the


execution plan) it may indicate that an appropriate
concatenated index is missing.
• Avoid index merges especially if using rule based optimizer
Minimize table lookups in queries
Join Techniques
• Sort-merge joins
Sort merge join does not require indexes. Each table is first sorted
on the column values used to join the tables and then merges the
two sorted result set into one.
• Nested loops join
Nested loop involves an index on at least one of the table. In this
case a full table scan is done on one table. For every row found a
lookup is performed on the second table (usually the one which is
indexed)
• Hash Join
In a hash join, a hash table is constructed for the larger table. The
smaller table is then scanned and the hash table is then used to find
matching rows in the larger table
Using Join Techniques

• Use nested loops when only a small subset of the rows


needs to be accessed and an index is available to support
it.
• Use sort and hash merge if joining most or all rows of the
tables.
• When determining the best join order try to start with the
table which will return the smallest number of rows,
providing that the subsequent tables can be joined
efficiently.
Controlling Joins with Hints

• The ORDERED hint tells the optimizer to join the tables in


the exact order in which it appears in the FROM clause.
• Use hints like FULL and INDEX.
• The hints USE_NL, USE_MERGE and USE_HASH can
force a particular join method.
EXISTS vs IN Clause

• An IN subquery is only executed once, while an EXISTS


subquery is executed once per row of parent query.
• An IN subquery might not be able to take advantage of
indexes on the subquery table, while EXISTS can.
• An EXISTS subquery might not be able to take advantage
of indexes on the parent table, while IN can.
• The optimizer sometimes automatically translates IN-based
subqueries into a join.
Anti-joins

• When using a rule-based optimizer avoid using NOT IN to


perform anti-joins.
• Use NOT EXISTS.
• Cost based optimizer treats both equally whereas the rule
based optimizer performs the NOT EXISTS more efficiently
• MINUS operators can be used efficiently to perform anti-
joins if the number and type in each query match.
Sorts

• Avoid unnecessary use of DISTINCT.


• Use UNION ALL in place of UNION, if the duplicate rows
need not be eliminated.
Aggregate Operations

• COUNT(*) goes for a full table scan. However Oracle has


some special optimization for it.
• COUNT(0) also goes for a full table scan however is
slower than count(*).
• COUNT(fld_name) is faster than the above two if the
fld_name is indexed.
• Where ever possible use WHERE to eliminate rows before
grouping. Use HAVING only with group functions.
• Try translating an INTERSECT statement into a join.
• When performing a MINUS operation consider re-coding it
into an anti-join using HASH_AJ hint.
Optimizing DML (1 of 4)
• Optimize WHERE clause.
• TRUNCATE tables, if possible, instead of DELETEing them
• Indexes add to the overhead of INSERT, UPDATE and DELETE. Avoid
over indexing, specially for columns which are frequently updated.
• Use array inserts.
• Use SET TRANSACTION options where possible
– USE ROLLBACK SEGMENT <segment name>
– READ ONLY
• Since COMMITing a transaction involves an I/O overhead, COMMIT
infrequently.
• Avoid arithmetic calculations in SQL. Perform this work in the program
code.
Optimizing DML (2 of 4)
• Retrieve only the columns necessary. Do not use SELECT *.
• Specify the fields in an insert statement, even if all fields are inserted.
• Always try to use joins instead of sub-queries within queries.
• Do not retrieve columns that are used for equal qualification in the predicate.

• Avoid use of NOT (!=, <>, etc.) in the WHERE clause, use BETWEEN, '>='
'<=', or '>' '<'.
• Use column names in the ORDER BY clause.
• Use ORDER BY only when absolutely necessary and minimize the result
set by using additional constraints in the WHERE clause.
Optimizing DML (3 of 4)

• Be careful in the use of GROUP BY. Oracle will sort the


answer set.
• Validate requirements for ORDER BY DESCENDING. This
will cause a sort regardless of indexes.
• Use DECODE if possible, as it avoids scanning the same
rows repeatedly.
• Use appropriate data types in SQL. When using a variable
as a bind variable ensure the data type match. An implicit
type conversion causes an index to be disregarded.
• Place the “Driving Table” at the END of the FROM clause.
Oracle reads the tables from last to first (right to left).
Optimizing DML (4 of 4)
• Use ROWID for fast updates:
SELECT rowid, balance
INTO rid,bal
FROM policy
WHERE policy_num=5;
UPDATE policy
SET balance=10
WHERE rowid=rid;
Thank You

Vous aimerez peut-être aussi