Optimizing a SQL statement
Introduction
As a DBA, you
are responsible for optimizing a SQL
statement using the EXPLAIN PLAN statement
in case of performance problems. Your job�s
responsibilities dictate that you should at
least be informed of the following basic
fundamental subjects:
Using the
EXPLAIN PLAN statement
Creating the
PLAN_TABLE table
Submitting a
SQL statement using the EXPLAIN PLAN
statement
Using the SET
STATEMENT_ID clause
Recalling the
EXECUTION plan from the PLAN_TABLE table
Understanding
of the following operations:
TABLE ACCESS
FULL
TABLE ACCESS
BY INDEX
INDEX UNIQUE
SCAN
NESTED LOOPS
MERGE JOIN
FILTER
SORT AGGREGATE
Commands:
START %ORACLE_HOME%
EXPLAIN PLAN
SET STATEMENT_ID=
Hands-on
In this
exercise you will learn how to use the
explain plan statement to determine how the
optimizer will execute the query in
question.
First, let's
connect to SQLPlus as the ORACLE user.
SQL> CONNECT oracle/learning
Check to see
if the PLAN_TABLE exists in the user's
schema.
SQL> DESC plan_table
Create
PLAN_TABLE
In order to
optimize a SQL statement, you execute the
EXPLAIN PLAN statement to populate a list
plan of execution in PLAN_TABLE. Then you
write a SQL statement against the table to
query a plan of execution list generated by
EXPLANIN PLAN.
If PLAN_TABLE
does not exist, run the utlxplan.sql script
provided in the rdbmsfolder to create the
PLAN_TABLE table.
SQL> START %ORACLE_HOME%
Now, the
PLAN_TABLE table was created.
Check the
number of records in the table.
SQL> SELECT
count(1)
FROM
plan_table
/
There should
be no records in the table.
Evaluate a SQL
statement
Submit a query
to the database using the EXPLAIN PLAN
statement, so that the database will list
the plan of execution. Use the SET
STATEMENT_ID clause to identify the plan for
later review. You should have one single
unique statement_id for each specific SQL
statement that you want to optimize.
SQL> EXPLAIN
PLAN
SET
STATEMENT_ID='MY_FIRST_TEST'
INTO
plan_table FOR
SELECT
last_name, trade_date,
sum(shares_owned*current_price)
portfolio_value
FROM
customers, portfolio, stocks s
WHERE id =
customer_id and stock_symbol = symbol
AND trade_date
= (SELECT max(trade_date) FROM stocks
WHERE symbol =
s.symbol)
GROUP BY
last_name, trade_date;
Check the
number of records in the table again.
SQL> SELECT
count(1)
FROM
plan_table
/
Now, there
should be at least 13 records in the table.
Display the
result of the SQL statement evaluation
Now, recall
the execution plan from the PLAN_TABLE
table.
SQL> SELECT
id, parent_id,
lpad(' ',
2*(level-1)) || operation || ' ' ||
options || ' '
|| object_name || ' ' ||
decode (id, 0,
'Cost = ' || position) "Query_Plan"
FROM
plan_table
START WITH id
= 0 and STATEMENT_ID = 'MY_FIRST_TEST'
CONNECT BY
PRIOR ID = PARENT_ID
AND
STATEMENT_ID = 'MY_FIRST_TEST'
/
How to read
PLAN_TABLE
Now, assuming
the following is an output of the above
query, let's learn how to read the output
report.
The previous
output report will be read this way. Notice
that the PARENT_ID and ID columns show a
child and parent relationship.
ID PARENT_ID
Query_Plan
--- ----------
----------------------------------------------
0 SELECT STATEMENT Cost =
SORT GROUP BY
"SORT GROUP
BY" means Oracle will perform a sort on the
data obtained for the user.
1 0 SORT GROUP BY
FILTER
"FILTER" means
that this is an operation that adds
selectivity to a TABLE ACCESS FULL
operation, based on the contents of the
where clause.
2 1 FILTER
NESTED LOOPS
"NESTED LOOPS"
indicates that the join statement is
occurring.
3 2 NESTED LOOPS
MERGE JOIN
"MERGE JOIN"
indicates that the join statement is
occurring.
4 3 MERGE JOIN
SORT JOIN
"SORT JOIN"
indicates that the join statement is
sorting. "TABLE ACCESS FULL" means that
Oracle will look at every row in the table
(slowest way).
5 4 SORT JOIN
6 5 TABLE
ACCESS FULL STOCKS
7 4 SORT JOIN
8 7 TABLE
ACCESS FULL PORTFOLIO
TABLE ACCESS
BY INDEX
"TABLE ACCESS
BY INDEX" means that Oracle will use the
ROWID method to find a row in the table. It
is very fast.
9 3 TABLE
ACCESS BY INDEX ROWID CUSTOMERS
INDEX UNIQUE
SCAN
"INDEX UNIQUE
SCAN" means Oracle will use the primary or
unique key. This is the most efficient way
to search an index.
10 9 INDEX UNIQUE SCAN SYS_C003126
SORT AGGREGATE
"SORT
AGGREGATE" means Oracle will perform a sort
on the data obtained for the user.
11 2 SORT
AGGREGATE
12 11 TABLE
ACCESS FULL STOCKS
Read your
output and see what the problem of the query
is
Questions:
Q: How do you
optimize a SQL statement?
Q: How do you
identify that a SQL statement is not
optimized?
Q: Describe
the EXPLAIN PLAN statement?
Q: How do you
create the PLAN_TABLE table?
Q: Describe
the use of the SET STATEMENT_ID clause?
Q: Describe
the following operation in PLAN_TABLE?
TABLE
ACCESS FULL
TABLE
ACCESS BY INDEX
INDEX
UNIQUE SCAN
NESTED
LOOPS
MERGE
JOIN
FILTER
SORT
AGGREGATE
Q: What does
the following SQL statement?
SQL> EXPLAIN
PLAN
SET
STATEMENT_ID='MY_FIRST_TEST'
INTO
plan_table FOR
SELECT
last_name, trade_date,
sum(shares_owned*current_price)
portfolio_value
FROM
customers, portfolio, stocks s
WHERE id =
customer_id and stock_symbol = symbol
AND trade_date
= (SELECT max(trade_date) FROM stocks
WHERE symbol =
s.symbol)
GROUP BY
last_name, trade_date
/
Q: What does
the following SQL statement?
SQL> SELECT
id, parent_id,
lpad(' ',
2*(level-1)) || operation || ' ' ||
options || ' '
|| object_name || ' ' ||
decode (id, 0,
'Cost = ' || position) "Query_Plan"
FROM
plan_table
START WITH id
= 0 and STATEMENT_ID = 'MY_FIRST_TEST'
CONNECT BY
PRIOR ID = PARENT_ID
AND
STATEMENT_ID = 'MY_FIRST_TEST'
/
Q: How do you
read the following PLAN_TABLE output?
ID PARENT_ID
Query_Plan
--- ----------
----------------------------------------------
0 SELECT
STATEMENT Cost =
1 0 SORT GROUP BY
2 1 FILTER
3 2 NESTED
LOOPS
4 3 MERGE JOIN
5 4 SORT JOIN
6 5 TABLE
ACCESS FULL STOCKS
7 4 SORT JOIN
8 7 TABLE
ACCESS FULL PORTFOLIO
9 3 TABLE
ACCESS BY INDEX ROWID CUSTOMERS
10 9 INDEX
UNIQUE SCAN SYS_C003126
11 2 SORT
AGGREGATE
12 11 TABLE
ACCESS FULL STOCKS
|