0% found this document useful (0 votes)
88 views

Oracle Perf Presentation

Oracle Performance

Uploaded by

modem
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
88 views

Oracle Perf Presentation

Oracle Performance

Uploaded by

modem
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 20

SQL statement processed internally

Sqlplusscott/tiger@prod
SQL>select * from emp;
SQL>update emp set sallary=30000 where empid=10;
SQL>commit;
1. Once we hit sqlplus statement as above client process(user)
access sqlnet listener.
2. Sql net listener confirms that DB is open for buisness & create
server process.
3. Server process allocates PGA. Connected Message returned to
user.
4. SQL>select * from emp;
5. Server process checks the SGA to see if data is already in buffer
cache.
6. If not then data is retrived from disk and copied into SGA (DB
Cache).
7. Data is returned to user via PGA & server process.
8. Now another statement is SQL>Update emp set sallary=30000
where empid=10;
9. Server process (Via PGA) checks SGA to see if data is already
there in buffer cache.
10. In our situation chances are the data is still in the SGA (DB

15. Newest SCN obtained from control file.


16. Data in DB cache is marked as Updated and ready for
saving.
17. commit palced into redo buffer.
18. LGWR writes redo buffer contents to redo log files &
remove from redo buffer.
19. Control file is updated with new SCN.
20. Commit complete message return to user.
21. Update emp table in datafile & update header of datafile
with latest SCN.
22. SQL>exit;
23. Unsaved changes are rolled back.
24. Server process deallocates PGA.
25. Server process terminates.
26. After some period of time redo log are archived by ARCH
process.

EXPLAIN PLAN Usage


When an SQL statement is passed to the server the Cost Based
Optimizer (CBO) uses database statistics to create an execution plan
which it uses to navigate through the data
-- Creating a shared PLAN_TABLE prior to 11g
SQL> CONN sys/password AS SYSDBA Connected
SQL> @$ORACLE_HOME/rdbms/admin/utlxplan.sql
SQL> GRANT ALL ON sys.plan_table TO public;
SQL> CREATE PUBLIC SYNONYM plan_table FOR sys.plan_table;
AUTOTRACE The Easy Option
SQL> SET AUTOTRACE ON
SQL> SELECT *
2 FROM emp e, dept d
3 WHERE e.deptno = d.deptno
4 AND e.ename = 'SMITH';
EMPNO ENAME
JOB
MGR HIREDATE
SAL
COMM
---------- ---------- --------- ---------- --------- ---------- ---------DEPTNO
DEPTNO DNAME
LOC
---------- ---------- -------------- ------------7369 SMITH
CLERK
7902 17-DEC-80
800

Execution Plan
---------------------------------------------------------0
SELECT STATEMENT Optimizer=CHOOSE
1 0 NESTED LOOPS
2 1
TABLE ACCESS (FULL) OF 'EMP'
3 1
TABLE ACCESS (BY INDEX ROWID) OF 'DEPT'
4 3
INDEX (UNIQUE SCAN) OF 'PK_DEPT' (UNIQUE)
Statistics
---------------------------------------------------------81 recursive calls
4 db block gets
27 consistent gets
0 physical reads
0 redo size
941 bytes sent via SQL*Net to client
425 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

SQL> EXPLAIN PLAN SET STATEMENT_ID = Sekhar' FOR


2 SELECT *
3 FROM emp e, dept d
4 WHERE e.deptno = d.deptno
5 AND e.ename = 'SMITH';
Explained.
SQL> @explain.sql Sekhar
PLAN
OBJECT_NAME
OBJECT_TYPE
BYTES COST PARTITION_START PARTITION_STOP
-------------------------------------- --------------- --------------- ----- ------------------- --------------Select Statement
57
4
1.1 Nested Loops
57
4
2.1 Table Access (Full)
EMP
TABLE
37
3
2.2 Table Access (By Index Rowid) DEPT
TABLE
20
1
3.1 Index (Unique Scan)
PK_DEPT
INDEX
(UNIQUE)
0
5 rows selected.

DBMS_XPLAN : Display Oracle Execution Plans


CONN scott/tiger
EXPLAIN PLAN FOR
SELECT *
FROM emp e, dept d
WHERE e.deptno = d.deptno
AND e.ename = 'SMITH';
SET LINESIZE 130
SET PAGESIZE 0
SELECT *
FROM TABLE(DBMS_XPLAN.DISPLAY);
--------------------------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost
(%CPU)| Time
|
--------------------------------------------------------------------------------------| 0 | SELECT STATEMENT
|
|
1 | 58 |
4 (0)|
00:00:01 |
| 1 | NESTED LOOPS
|
|
|
|
|
|
| 2 | NESTED LOOPS
|
|
1 | 58 |
4 (0)|

Predicate Information (identified by operation id):


--------------------------------------------------3 - filter("E"."ENAME"='SMITH')
4 - access("E"."DEPTNO"="D"."DEPTNO")
18 rows selected.
SQL>
The DBMS_XPLAN.DISPLAY function can accept 3 optional
parameters:
table_name - Name of the PLAN_TABLE, default value
'PLAN_TABLE'.
statement_id - Statement id of the plan to be displayed. The
default value is NULL, which displays the most recent execution
plan in the PLAN_TABLE.
format - Controls the level of detail displayed, default value
'TYPICAL'. Other values include 'BASIC', 'ALL', 'SERIAL'. There is
also an undocumented 'ADVANCED' setting.
EXPLAIN PLAN SET STATEMENT_ID='TSH' FOR
SELECT *

SET LINESIZE 130


SELECT *
FROM
TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE','TSH','BASIC'));
Plan hash value: 3625962092
-----------------------------------------------| Id | Operation
| Name |
-----------------------------------------------| 0 | SELECT STATEMENT
|
|
| 1 | NESTED LOOPS
|
|
| 2 | NESTED LOOPS
|
|
| 3 | TABLE ACCESS FULL
| EMP
|
| 4 | INDEX UNIQUE SCAN
| PK_DEPT |
| 5 | TABLE ACCESS BY INDEX ROWID| DEPT
-----------------------------------------------12 rows selected.

DISPLAY_CURSOR Function
CONN / AS SYSDBA
GRANT SELECT ON v_$session TO scott;
GRANT SELECT ON v_$sql TO scott;
GRANT SELECT ON v_$sql_plan TO scott;
GRANT SELECT ON v_$sql_plan_statistics_all TO scott;
CONN scott/tiger
SELECT *
FROM emp e, dept d
WHERE e.deptno = d.deptno
AND e.ename = 'SMITH';
SET LINESIZE 130
SELECT *
FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(format => 'ADVANCED'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------SQL_ID gu62pbk51ubc3, child number 0
------------------------------------SELECT * FROM emp e, dept d WHERE e.deptno = d.deptno AND
= 'SMITH'

e.ename

Plan hash value: 3625962092


---------------------------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost (%CPU)| Time
|
---------------------------------------------------------------------------------------| 0 | SELECT STATEMENT
|
|
|
|
4 (100)|
|
| 1 | NESTED LOOPS
|
|
|
|
|
|
| 2 | NESTED LOOPS
|
|
1 | 58 |
4 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL
| EMP
|
1 | 38 |
3 (0)| 00:00:01 |
|* 4 | INDEX UNIQUE SCAN
| PK_DEPT |
1|
|
0 (0)|
|
| 5 | TABLE ACCESS BY INDEX ROWID| DEPT |
1 | 20 |
1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):


------------------------------------------------------------1 - SEL$1
3 - SEL$1 / E@SEL$1
4 - SEL$1 / D@SEL$1
5 - SEL$1 / D@SEL$1
Outline Data
------------/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('11.2.0.2')
DB_VERSION('11.2.0.2')
ALL_ROWS
OUTLINE_LEAF(@"SEL$1")
FULL(@"SEL$1" "E"@"SEL$1")
INDEX(@"SEL$1" "D"@"SEL$1" ("DEPT"."DEPTNO"))
LEADING(@"SEL$1" "E"@"SEL$1" "D"@"SEL$1")
USE_NL(@"SEL$1" "D"@"SEL$1")
NLJ_BATCHING(@"SEL$1" "D"@"SEL$1")
END_OUTLINE_DATA
*/
Predicate Information (identified by operation id):
--------------------------------------------------3 - filter("E"."ENAME"='SMITH')
4 - access("E"."DEPTNO"="D"."DEPTNO")
Column Projection Information (identified by operation id):
----------------------------------------------------------1 - "E"."EMPNO"[NUMBER,22], "E"."ENAME"[VARCHAR2,10], "E"."JOB"[VARCHAR2,9],
"E"."MGR"[NUMBER,22], "E"."HIREDATE"[DATE,7], "E"."SAL"[NUMBER,22],
"E"."COMM"[NUMBER,22], "E"."DEPTNO"[NUMBER,22], "D"."DEPTNO"[NUMBER,22],
"D"."DNAME"[VARCHAR2,14], "D"."LOC"[VARCHAR2,13]
2 - "E"."EMPNO"[NUMBER,22], "E"."ENAME"[VARCHAR2,10], "E"."JOB"[VARCHAR2,9],
"E"."MGR"[NUMBER,22], "E"."HIREDATE"[DATE,7], "E"."SAL"[NUMBER,22],
"E"."COMM"[NUMBER,22], "E"."DEPTNO"[NUMBER,22], "D".ROWID[ROWID,10],
"D"."DEPTNO"[NUMBER,22]
3 - "E"."EMPNO"[NUMBER,22], "E"."ENAME"[VARCHAR2,10], "E"."JOB"[VARCHAR2,9],
"E"."MGR"[NUMBER,22], "E"."HIREDATE"[DATE,7], "E"."SAL"[NUMBER,22],
"E"."COMM"[NUMBER,22], "E"."DEPTNO"[NUMBER,22]
4 - "D".ROWID[ROWID,10], "D"."DEPTNO"[NUMBER,22]
5 - "D"."DNAME"[VARCHAR2,14], "D"."LOC"[VARCHAR2,13]

TKPROF

Generating SQL Trace Files


-- All versions.
SQL> ALTER SESSION SET sql_trace=TRUE;
SQL> ALTER SESSION SET sql_trace=FALSE;
SQL> EXEC DBMS_SESSION.set_sql_trace(sql_trace => TRUE);
SQL> EXEC DBMS_SESSION.set_sql_trace(sql_trace => FALSE);
SQL> ALTER SESSION SET EVENTS '10046 trace name context forever, level 8';
SQL> ALTER SESSION SET EVENTS '10046 trace name context off';
SQL> EXEC DBMS_SYSTEM.set_sql_trace_in_session(sid=>123, serial#=>1234,
sql_trace=>TRUE);
SQL> EXEC DBMS_SYSTEM.set_sql_trace_in_session(sid=>123, serial#=>1234,
sql_trace=>FALSE);
SQL> EXEC DBMS_SYSTEM.set_ev(si=>123, se=>1234, ev=>10046, le=>8, nm=>' ');
SQL> EXEC DBMS_SYSTEM.set_ev(si=>123, se=>1234, ev=>10046, le=>0, nm=>' ');
-- All versions, requires DBMS_SUPPORT package to be loaded.
SQL> EXEC DBMS_SUPPORT.start_trace(waits=>TRUE, binds=>FALSE);
SQL> EXEC DBMS_SUPPORT.stop_trace;
SQL> EXEC DBMS_SUPPORT.start_trace_in_session(sid=>123, serial=>1234, waits=>TRUE,
binds=>FALSE);
SQL> EXEC DBMS_SUPPORT.stop_trace_in_session(sid=>123, serial=>1234);

TRACE File Identifier


ALTER SESSION SET TRACEFILE_IDENTIFIER = "MY_TEST_SESSION";

File Location
SELECT value
FROM v$diag_info
WHERE name = 'Default Trace File';

Trace Levels
SQL> ALTER SESSION SET EVENTS '10046 trace name context forever, level 12';

Access Methods in detail


Full Table Scan (FTS)
Index lookup
SELECT STATEMENT [CHOOSE] Cost=1
TABLE ACCESS BY ROWID EMP [ANALYZED]
INDEX UNIQUE SCAN EMP_I1

There are 4 methods of index lookup:


index unique scan
index range scan
index full scan
index fast full scan
Rowid
SQL> explain plan for select * from dept where rowid = ':x';
Query Plan
-----------------------------------SELECT STATEMENT [CHOOSE] Cost=1
TABLE ACCESS BY ROWID DEPT [ANALYZED]

Join Types
Sort Merge Join (SMJ)
Nested Loops (NL)
Hash Join
Sort Merge Join
MERGE
/
\
SORT
SORT
|
|
Row Source 1 Row Source 2
Nested Loops
First we return all the rows from row source 1 Then we probe row source 2 once for each
row returned from row source 1
Row source 1
~~~~~~~~~~~~
Row 1 --------------- Probe ->
Row source 2
Row 2 --------------- Probe ->
Row source 2
Row 3 --------------- Probe ->
Row source 2
Row source 1 is known as the outer table
Row source 2 is known as the inner table

Hash Join
SQL> explain plan for
select /*+ use_hash(emp) */ empno
from emp,dept
where emp.deptno = dept.deptno;
Query Plan
---------------------------SELECT STATEMENT [CHOOSE] Cost=3
HASH JOIN
TABLE ACCESS FULL DEPT
TABLE ACCESS FULL EMP

Cartesian Product
SQL> explain plan for
select emp.deptno,dept,deptno
from emp,dept
Query Plan
-----------------------------SLECT STATEMENT [CHOOSE] Cost=5
MERGE JOIN CARTESIAN
TABLE ACCESS FULL DEPT
SORT JOIN
TABLE ACCESS FULL EMP

Operations
Operations that show up in explain plans

sort
filter
view
Sorts
In the following example the select contains an inline view which cannot be merged:
SQL> explain plan for
select ename,tot
from emp,
(select empno,sum(empno) tot from big_emp group by empno) tmp
where emp.empno = tmp.empno;
Query Plan
-----------------------SELECT STATEMENT [CHOOSE]
HASH JOIN
TABLE ACCESS FULL EMP [ANALYZED]
VIEW
SORT GROUP BY
INDEX FULL SCAN BE_IX

Parallel Query
select /*+ parallel(B,4) parallel(A,4) */
A.dname, avg(B.sal), max(B.sal)
from dept A, emp B
where A.deptno = B.deptno
group by A.dname
order by max(B.sal), avg(B.sal) desc;
OBJECT_NAME
OBJECT_NODE OTHER
------------------------------- ----------- ------SELECT STATEMENT
Cost = ??
SORT ORDER BY
:Q55004
**[7]**
SORT GROUP BY
:Q55003
**[6]**
MERGE JOIN
:Q55002
**[5]**
SORT JOIN
:Q55002
**[4]**
TABLE ACCESS FULL emp :Q55001
**[2]**
SORT JOIN
:Q55002
**[3]**
TABLE ACCESS FULL dept :Q55000
**[1]**
Execution Plan #2 -- OTHER column
**[1]** (:Q55000) "PARALLEL_FROM_SERIAL"
Serial execution of SELECT DEPTNO, DNAME FROM DEPT
**[2]** (:Q55001) "PARALLEL_TO_PARALLEL"
SELECT /*+ ROWID(A1)*/
A1."DEPTNO" C0, A1."SAL" C1
FROM "EMP" A1
WHERE ROWID BETWEEN :1 AND :2
**[3]** (:Q55002) "PARALLEL_COMBINED_WITH_PARENT"
**[4]** (:Q55002) "PARALLEL_COMBINED_WITH_PARENT"
**[5]** (:Q55002) "PARALLEL_TO_PARALLEL"
SELECT /*+ ORDERED USE_MERGE(A2)*/
A2.C1 C0, A1.C1 C1
FROM :Q55001 A1,:Q55000 A2
WHERE A1.C0=A2.C0
**[6]** (:Q55003) "PARALLEL_TO_PARALLEL"
SELECT MAX(A1.C1) C0, AVG(A1.C1) C1, A1.C0 C2
FROM :Q55002 A1
GROUP BY A1.C0
**[7]** (:Q55004) "PARALLEL_FROM_SERIAL"

Quick Fixes
There are a number of very common SQL problems that are easy to identify and
easy to fix.
Are the underlying tables and indexes analyzed?
Does the SQL already have optimizer hints?
Do you have any Cartesian Products?
To find out whether your SQL is performing a Cartesian Product, run it through
Explain Plan and search for a step that looks like this:
MERGE JOIN (CARTESIAN)
There are several situations where Oracle will use a Cartesian Product
You have not specified any join conditions in the WHERE clause of your SQL. For
example:
SELECT a.column1, b.column3
FROM table_a a, table_b b
WHERE a.column9 = 'X'
AND b.column5 >= to_date('13-JAN-2003','DD-MON-YYYY')
For low volume SQLs, are there any Full Table/Partition Scans?
Full Table Scans
Full table scans have an image problem. Many Oracle developers - usually those
working on OLTP systems - are told early in their careers that Full Table Scans are
bad. Period! Many will then hold on to this prejudice and never learn the truth.

Full Table Scans can be good when:


Used on a small table (< 500 rows)
Used in a query returning more than a few percent of the rows in a table (see
High Volume SQLs for a brief discussion on this point)
Used in a Sort-Merge or Hash join, but only when these join methods are
intended.
Full Table Scans are bad when:
Used on a large table where indexed or hash cluster access is preferred.
Used on a medium-large table (> 500 rows) as the outer table of a Nested Loop
join.
Used on a medium-large table (> 500 rows) in a Nested Sub-Query.
Used in a Sort-Merge or Hash join when a Nested Loop join is preferred.
To check for a full table scan, first run your SQL through Explain Plan and check
for a line like:
TABLE ACCESS (FULL) MY_TABLE_NAME
Do you have 5 or more tables in a single join?
Multiple Table Joins
NP-Hard Problems
A three table join has three times as many alternatives,
a four table join has four times the alternatives of a three table join.
In general, the number of possible execution paths for a join statement is
proportional to n! (ie. n x n-1 x n-2 x ... x 2 x 1),
where n is the number of tables in the join.

What to look for


If you have a table join (ie. a FROM clause) with five or more tables, and you have
not included a hint for join order (eg. ORDERED or LEADING ), then Oracle may be
joining the tables in the wrong order.
Run your SQL through Explain Plan and check the order that the tables are
processed.
Say we have a SQL with five tables (A-E) in the FROM clause, and the following
joins:
A <-> B
A <-> C
B <-> D
D <-> E
If the Explain Plan showed the tables in the order A, B, C, D, E, then this would be
OK.
However if it showed A, B, C, E, D, then there would be a problem because we
need the columns from D to join to E, but D is joined last.
In this case, table E joins to both table D and table A, however the join to table A
is a range operator (>=). It may seem obvious that table E should be joined after
table D, but this is exactly the sort of case where Oracle can mess up.
How to fix it
If the tables are being joined in the wrong order, you can supply a hint to suggest
a better order.
If Oracle is just starting with the wrong table, try a LEADING hint to suggest the
best table to start with. SQLs with equi-joins will often get the rest of the joins
right if only they know where to start.

Execution Plan
---------------------------------------------------------0
SELECT STATEMENT Optimizer=CHOOSE
1 0 NESTED LOOPS
2 1
TABLE ACCESS (FULL) OF 'EMP'
3 1
TABLE ACCESS (BY INDEX ROWID) OF 'DEPT'
4 3
INDEX (UNIQUE SCAN) OF 'PK_DEPT' (UNIQUE)
Statistics
---------------------------------------------------------81 recursive calls
4 db block gets
27 consistent gets
0 physical reads
0 redo size
941 bytes sent via SQL*Net to client
425 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

You might also like