Professional Documents
Culture Documents
2015-K-Db-Herv Schweitzer-Oracle Database Perfomance Tuning - Wie Angehen Fa Dbi Services - Praesentation
2015-K-Db-Herv Schweitzer-Oracle Database Perfomance Tuning - Wie Angehen Fa Dbi Services - Praesentation
Hervé Schweitzer
Chief Technology Officer
Principal consultant
Nicolas Jardot
Senior Consultant
Oracle Certified Professional Database 12c
www.dbi-services.com/DMK
1. Introduction
2. Cost Based Optimizer
3. Access Path
4. Monitoring performance
5. Conclusion
Percentiles
> Do you want all user interactions to be less than 1 second
> Or do you want that 90% of user interactions are less than ½ second?
Scalability
> Even when the response time is not affected, scalability issues must be
addressed proactively
Resource consumption
> Even when the response time is not affected, we want to use less
resources:
> Use less CPU because we pay licenses on CPU
> Use less bandwidth shared with other systems
> Save energy
Methodology to
> Address the real issue
> Fix the root cause (workarounds and fixes)
1. Introduction
2. Cost Based Optimizer Understand
3. Access Path
4. Monitoring performance Analyze
5. Conclusion
1. Introduction
2. Cost Based Optimizer
3. Access Path
4. Monitoring performance
5. Conclusion
The optimizer
> Evaluates the different ways to access data
> Chooses the most efficient
> Choose between 17 possible > Computes cost for several execution
access paths plans
> Lower ranked access path is > Selects plan with the lowest cost
chosen
> De-supported since Oracle 10g > Available since Oracle 7, default since
Oracle 10g
RBO cannot be used with new objects types or new features
It shall not be used in recent releases
Don’t use anymore the hint /*+ RULE */
Oracle Performance Tuning – Cost Based Optimizer Page 6
19.11.15
Optimizer overview
Optimizer vocabulary
Row set
> Table, View, or result of a Join or Group by
Predicate
> Filter condition on a row set
Example: name = 'SMITH'
Selectivity
> How many rows returned from a row set using a predicate?
> Value from 0.0 to 1.0
Example: selectivity = 0.1, table = 1000 rows
0.1 * 1000 = 100 returned rows
Cost
> Estimate amount of work required for one operation
> Expressed as CPU, I/O and memory
> I/O cost not expressed in rows but in number of I/O calls
> The cost value is proportional to the estimated time
> The cost unit is the estimated time for one I/O
Query Transformer
Data Dictionary
Plan Generator
Cost Estimator
SNAME VALUE
------------------------------ ----------------------------------
STATS_RETENTION 31
SYS_FLAGS 1
APPROXIMATE_NDV TRUE
CASCADE DBMS_STATS.AUTO_CASCADE
ESTIMATE_PERCENT DBMS_STATS.AUTO_SAMPLE_SIZE
DEGREE NULL
METHOD_OPT FOR ALL COLUMNS SIZE AUTO
NO_INVALIDATE DBMS_STATS.AUTO_INVALIDATE
GRANULARITY AUTO
PUBLISH TRUE
STALE_PERCENT 10
INCREMENTAL FALSE
INCREMENTAL_INTERNAL_CONTROL TRUE
AUTOSTATS_TARGET AUTO
exec dbms_stats.set_[global|database|schema|table]_prefs(
ownname =>'HR',
tabname =>'EMPLOYEES',
pname =>'ESTIMATE_PERCENT',
pvalue =>'100');
1 1 2 2 2 2 2 2 3 3 3 4
1 2 3 4
1 1 2 2 2 2 2 2 3 3 3 4
1 7 2 2 4
1 1 2 2 2 2 2 2 3 3 3 4
1 2 4
2 6 1
SQL> exec
dbms_stats.gather_system_stats(gathering_mode=>'NOWORKLOAD');
Parse
SQL statement to optimize
> Apply transformation and rewrite rules
Binding
System statistics
> Use to adjust I/O and CPU costs
Execute
Object statistics
> Number of rows, Histograms Fetch
> Apply selectivity to get the cardinality
Close Cursor
SQL Parsing /
Execution
Statement Optimization
• Syntax check
Parent • Semantic check
cursor Parsing • Check access rights
• Query rewrite
Logical • Optimizer transformation
Optimization
Child
cursor
• Syntax check
Parent • Semantic check
cursor Parsing • Check access rights
• Query rewrite
Logical • Optimizer transformation
Optimization
Child
cursor
exec :v_id:= 5;
exec :v_name:='SMITH';
exec :v_date:=to_date('01/08/14','DD/MM/YY');
C COUNT(*)
- ----------
M 4
F 1
C COUNT(*)
- ----------
M 613
F 312
1. Introduction
2. Cost Based Optimizer
3. Access Path
4. Monitoring performance
5. Conclusion
Sequential read
> Single-block read sequentially
> Usually used for direct block access like TABLE ACCESS BY ROWID
Scattered read
> Multi-block read into non adjacent memory locations
> Up to DB_FILE_MULTIBLOCK_READ_COUNT blocs in a single operation
> Usually used for large scans: FULL TABLE SCAN, INDEX FAST FULL SCAN
0 rows fetched.
Oracle Performance Tuning – Access Path Page 8
19.11.15
Table Access
How to lower the High Water Mark
HWM
0001 0004 0010
4 blocks 0002 0008 0011
0003 0006 0012
TRUNCATE TABLE
HWM
0 blocks
Recommendation
> Don’t set the db_file_multiblock_read_count
> If it needs to be set (I/O size is smaller), be sure to have
workload system statistics for optimizer to use them
2. With db_file_multiblock_read_count=64
direct path read block cnt 62 143
direct path read block cnt 64 73
Access by ROWID
> Is the fastest access to retrieve one row
> Is the slowest access to retrieve all the rows
Index is maintained
> New rows have new entries in the structure
> Leaf or branch blocks may be split when full
> When root is full, split add a new level
> Updating index value deletes the old value and adds the new one
150
100
200
300
400 100
100-200
100-200
350 250-300 200
150 300-400
350-400 300
250
100 100
250 350
300
150 200
300
150 350
400
200 200 400
100-220
100 250-400
200
300
400
100-150 100-200
250-300
350 250-300
150 200-220 350-400
350-400
250
220
100 100
200 250 350
150 150
220 300 400
200
ANSII syntax
> Join condition is explicit
select * from DEPT join EMP on DEPT.DEPTNO=EMP.DEPTNO
the inner table (index) and have a good #3 7521 WARD SALES
clustering factor #4 7566 JONES RESEARCH
> Bad if too many rows from outer table
Hash Join
> Builds a hash table from smaller input EMPNO ENAME DNAME
----------------------------------------------------------------------------
| Id | Operation | Name | Starts | A-Rows | Buffers |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 13 |
| 1 | NESTED LOOPS | | 1 | 3 | 13 |
|* 2 | TABLE ACCESS FULL | EMP | 1 | 3 | 8 |
| 3 | TABLE ACCESS BY INDEX ROWID| DEPT | 3 | 3 | 5 |
|* 4 | INDEX UNIQUE SCAN | PK_DEPT | 3 | 3 | 2 |
----------------------------------------------------------------------------
Nested Loop
> Outer table (EMP) has 3 rows after applying the ‘sal>=3000’ predicate
> for each of them the DEPT is accessed by a rowid
----------------------------------------------------------------------------
| Id | Operation | Name | Starts | A-Rows | Buffers |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 13 |
| 1 | NESTED LOOPS | | 1 | 3 | 13 |
| 2 | NESTED LOOPS | | 1 | 3 | 10 |
|* 3 | TABLE ACCESS FULL | EMP | 1 | 3 | 8 |
|* 4 | INDEX UNIQUE SCAN | PK_DEPT | 3 | 3 | 2 |
| 5 | TABLE ACCESS BY INDEX ROWID| DEPT | 3 | 3 | 3 |
----------------------------------------------------------------------------
Join Batching
> A first loop retrieves a vector of rowid
> A second loop retrieves the rows by batch
-----------------------------------------------------------------------
| Id | Operation | Name | Starts | A-Rows | Buffers | OMem |
-----------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 14 | 15 | |
|* 1 | HASH JOIN | | 1 | 14 | 15 | 1321K|
| 2 | TABLE ACCESS FULL| DEPT | 1 | 4 | 7 | |
| 3 | TABLE ACCESS FULL| EMP | 1 | 14 | 8 | |
-----------------------------------------------------------------------
Hash Join
> Builds a hash table with the inner row source
> Probes it from the outer row source
The order of tables can be swapped
> The smaller one is chosen to be the hash table
SQL> select
count(*),min(cust_year_of_birth),max(cust_year_of_birth)
from SALES join CUSTOMERS using(cust_id)
where amount>10;
SQL> select
count(*),min(cust_year_of_birth),max(cust_year_of_birth)
from SALES join CUSTOMERS using(cust_id)
where prod_id=20 and quantity>1;
Nested
Hash Join
Loop
Stats collector
TABLE 1 TABLE 2
Nested
Hash Join
Loop
Stats collector
TABLE 1 TABLE 2
Nested
Hash Join
Loop
Stats collector
TABLE 1 TABLE 2
> A lot of location id end with ‘0’ but the optimizer is not aware of it.
106 100
106 101 101 101
107 107 106 102
101 102
101 107 100
108 Sort to tempfile 102
buffer 108 108 102 sort
104 103
104 102 104
104 106
104 104 104
105 104
105 104 106
102 buffer Sort to tempfile 104
102 105 sort
107 103
100 107 100
100 107
103
103
buffer 103 Sort to tempfile 103
107
109
109 109
108
102 108 102
102 108
buffer Sort to tempfile
-----------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc|
-----------------------------------------------------------
| 0 | SELECT STATEMENT | | 1000 | 3907K| |
| 1 | SORT ORDER BY | | 1000 | 3907K| 4008K|
| 2 | TABLE ACCESS FULL| TEST | 1000 | 3907K| |
-----------------------------------------------------------
Recommended value
> Workarea_policy=auto at system level
> Good for OLTP
> Still good for large volume if Parallel Query is used
Workarea_policy=manual
> When we can allocate 1 our 2 GB
> At session level only, and controlling the total number of session
> Set sort_area_size and hash_area_size as needed
1. Introduction
2. Cost Based Optimizer
3. Access Path
4. Monitoring performance
5. Conclusion
User Database
execute() SQL*Net message from client
DB Time
cursor
SQL*Net message from client
Database OS storage
io_call()
block
DB Time
cursor
SQL*Net message from client
Facts to know
> Everything needs CPU: you will always have CPU consumption
> One session cannot use more than one CPU (except parallel query)
Process 2
> With load average of 10 all cores are overloaded despites the ‘75%’ idle
dbms_xplan.display:
> Display from PLAN_TABLE (result from EXPLAIN PLAN)
dbms_xplan.display_cursor:
> Display from V$SQL_PLAN (already executed cursor child)
dbms_xplan.display_AWR:
> Display from DBA_HIST_SQL_PLAN (stored by AWR)
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------
Plan hash value: 3315835386
--------------------------------------------------------------
| Id | Operation | Name | Cost (%CPU)|
--------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 (20)|
| 1 | HASH GROUP BY | | 5 (20)|
| 2 | NESTED LOOPS | | 4 (0)|
| 3 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 (0)|
| 4 | INDEX UNIQUE SCAN | PK_DEPT | 1 (0)|
| 5 | TABLE ACCESS FULL | EMP | 3 (0)|
--------------------------------------------------------------
SQL>
SQL> select job,dname,count(*) from EMP join DEPT using(deptno)
2 where deptno=:d group by job,dname;
-------------------------------------------------
| Id | Operation | Name |
-------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | HASH GROUP BY | |
| 2 | NESTED LOOPS | |
| 3 | TABLE ACCESS BY INDEX ROWID| DEPT |
| 4 | INDEX UNIQUE SCAN | PK_DEPT |
| 5 | TABLE ACCESS FULL | EMP |
-------------------------------------------------
1 - :D (NUMBER): 10
Session altered.
4 - access("DEPT"."DEPTNO"=:D)
5 - filter("EMP"."DEPTNO"=:D)
Note
Oracle Performance Tuning – Monitoring Performance
----- Page 25
19.11.15
- dynamic statistics used: dynamic sampling (level=2)
dbms_xplan
How to read an execution plan?
--------------------------------------------------------------
| Id | Operation | Name | Cost (%CPU)|
--------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 (20)|
| 1 | HASH GROUP BY | | 5 (20)|
| 2 | NESTED LOOPS | | 4 (0)|
| 3 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 (0)|
| 4 | INDEX UNIQUE SCAN | PK_DEPT | 1 (0)|
| 5 | TABLE ACCESS FULL | EMP | 3 (0)|
--------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("DEPT"."DEPTNO"=:D)
5 - filter("EMP"."DEPTNO"=:D)
Overview:
> Most of the time is I/O
> We need to improve the part of the plan that is doing lot of I/O
3. Lot of
2. Nested executions
Loops
4. I/O waits
1. Root cause:
Cardinality under estimated
Oracle Performance Tuning – Monitoring Performance Page 31
19.11.15
SQL Monitoring
Example: Nested Loop
(In RAC, must be run in each instance, with the right instance_number)
> www.orachrome.com
> www.lab128.com
> etc.
Oracle Performance Tuning – Monitoring Performance Page 37
19.11.15
Monitoring Performance
SQL> @?/rdbms/admin/awrrpt.sql
…
Specify the Report Type
~~~~~~~~~~~~~~~~~~~~~~~
AWR reports can be generated in the following formats. Please enter
the
name of the format at the prompt. Default value is 'html'.
Usage
> When Diagnostics Pack is licensed
> When investigating short issues (few seconds to few minutes)
> Easy to make load graphs (one row per sample / active session)
Tracefile location
with 10g:${ORA_ADMIN_SID}/udump
with 11g:_${ORACLE_DIAG}/diag/rdbms/…/<SID>/trace/<SID>_ora_<ID>.trc
Stop trace
SQL> exec
sys.dbms_monitor.serv_mod_act_trace_disable(service_name=>'APP',module
_name =>'New Order')
SQL> select * from v$diag_info where name='Diag Trace';
1. Introduction
2. Cost Based Optimizer
3. Access Path
4. Monitoring performance
5. Conclusion
What about
> Ratios?
> Rules of thumbs?
> Silver bullets?
major books:
> Jonathan Lewis - Cost Base Oracle Fundamentals
> Chris Antognini - Troubleshooting Oracle Performance
> Markus Winand - SQL Explained