Showing posts with label PERFORMANCE TUNING GUIDE. Show all posts
Showing posts with label PERFORMANCE TUNING GUIDE. Show all posts

Tuesday, 19 May 2026

PERFORMANCE TUNING GUIDE

                           ORACLE 19c DATABASE

PERFORMANCE TUNING GUIDE

Step-by-Step Reference for DBAs and Performance Engineers    

Step 1: Establish a Performance Baseline

 

Before tuning anything, you must understand how the database currently behaves. A baseline gives you a reference point to measure improvement.

 

1.1  Enable the Automatic Workload Repository (AWR)

AWR is the primary performance data collection mechanism in Oracle 19c. Verify it is licensed and active:

SELECT * FROM dba_hist_wr_control;

 

Set the snapshot interval and retention period:

BEGIN

  DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS(

    retention => 43200,   -- 30 days in minutes

    interval  => 60       -- Snapshot every 60 minutes

  );

END;

/

 

1.2  Take a Manual AWR Snapshot

Capture an immediate snapshot to start baseline collection:

EXEC DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT();

 

1.3  Generate an AWR Report

After a representative workload period (at least 1 hour), generate the AWR HTML report:

@$ORACLE_HOME/rdbms/admin/awrrpt.sql

 

Key sections to analyze in the AWR report:

       Top 10 Foreground Events — shows where sessions are waiting

       SQL Statistics — identifies high-load SQL statements

       Instance Activity Statistics — I/O, buffer cache, redo activity

       Memory Statistics — SGA/PGA sizing information

       Segment Statistics — top segments by logical/physical reads

 

1.4  Review Active Session History (ASH)

ASH provides real-time and historical session-level detail:

SELECT sample_time, session_id, event, wait_class,

       sql_id, blocking_session

FROM   v$active_session_history

WHERE  sample_time > SYSDATE - 1/24

ORDER  BY sample_time DESC;

 


 

Step 2: Tune Memory — SGA and PGA

 

Memory configuration has the most significant impact on database performance. Oracle 19c uses Automatic Memory Management (AMM) or manual component sizing.

 

2.1  Choose a Memory Management Strategy

 

Parameter / Strategy

Description

MEMORY_TARGET

Full AMM — Oracle manages SGA + PGA automatically. Simplest but less predictable.

SGA_TARGET

ASMM — Oracle auto-tunes SGA components within a fixed ceiling. Recommended for most workloads.

Manual sizing

You set each component explicitly. Best for very large or specialized systems.

 

2.2  Size the Buffer Cache

The buffer cache holds recently used data blocks. Target a high buffer cache hit ratio (> 99% for OLTP):

SELECT 1 - (phy.value / (cur.value + con.value)) AS hit_ratio

FROM   v$sysstat phy, v$sysstat cur, v$sysstat con

WHERE  phy.name = 'physical reads'

AND    cur.name = 'db block gets'

AND    con.name = 'consistent gets';

 

Increase if hit ratio is below 99% (and RAM is available):

ALTER SYSTEM SET db_cache_size = 8G SCOPE=BOTH;

 

2.3  Size the Shared Pool

The shared pool caches parsed SQL, PL/SQL code, and dictionary data. Monitor free memory:

SELECT name, bytes/1024/1024 AS mb_free

FROM   v$sgastat

WHERE  pool = 'shared pool'

AND    name = 'free memory';

 

Low free memory (< 10% of shared pool) indicates you need to increase it or reduce hard parsing:

ALTER SYSTEM SET shared_pool_size = 2G SCOPE=BOTH;

 

2.4  Configure PGA Memory

PGA is used for sort operations, hash joins, and bitmap operations. Use automatic PGA management:

ALTER SYSTEM SET pga_aggregate_target = 4G SCOPE=BOTH;

ALTER SYSTEM SET pga_aggregate_limit  = 8G SCOPE=BOTH;

 

Monitor PGA utilization:

SELECT name, value/1024/1024 AS mb

FROM   v$pgastat

WHERE  name IN ('aggregate PGA target parameter',

                'total PGA allocated',

                'cache hit percentage');

 

2.5  Review SGA Component Sizes (ASMM)

SHOW PARAMETER sga_target

SELECT component, current_size/1024/1024 AS mb_current,

       min_size/1024/1024 AS mb_min, max_size/1024/1024 AS mb_max

FROM   v$sga_dynamic_components

ORDER  BY current_size DESC;

 


 

Step 3: Identify and Tune High-Load SQL

 

Poorly written or unoptimized SQL is the most common cause of Oracle performance problems. Finding and fixing top SQL statements typically yields the highest ROI.

 

3.1  Find Top SQL by Elapsed Time

SELECT sql_id, executions, elapsed_time/1e6 AS elapsed_sec,

       elapsed_time/NULLIF(executions,0)/1e6 AS sec_per_exec,

       buffer_gets, disk_reads, SUBSTR(sql_text,1,80) AS sql_text

FROM   v$sqlstats

ORDER  BY elapsed_time DESC

FETCH  FIRST 20 ROWS ONLY;

 

3.2  Capture the Execution Plan

Always capture the actual (not estimated) execution plan:

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('&sql_id', NULL, 'ALLSTATS LAST'));

 

Explain plan for new SQL statements:

EXPLAIN PLAN FOR

  <your SQL here>;

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());

 

3.3  Common Plan Issues and Fixes

 

Plan Operation

Recommended Action

FULL TABLE SCAN

Add or rebuild indexes. Consider partitioning for large tables.

NESTED LOOPS on large sets

Evaluate HASH JOIN via hints or optimizer stats refresh.

High BUFFER GETS

Check for missing indexes, inefficient predicates, or bind variable peeking issues.

CARTESIAN JOIN

Missing or incorrect JOIN conditions — review the SQL logic.

High ESTIMATED vs ACTUAL rows

Gather fresh statistics: DBMS_STATS.GATHER_TABLE_STATS.

FILTER (wrong order)

Use SQL Profiles or hints to force better join order.

 

3.4  Gather Fresh Optimizer Statistics

BEGIN

  DBMS_STATS.GATHER_SCHEMA_STATS(

    ownname          => 'SCHEMA_NAME',

    estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,

    method_opt       => 'FOR ALL COLUMNS SIZE AUTO',

    degree           => 8,

    cascade          => TRUE

  );

END;

/

 

3.5  Use SQL Tuning Advisor

Oracle 19c's SQL Tuning Advisor automates analysis and recommends SQL Profiles, new indexes, or restructured queries:

DECLARE

  l_task VARCHAR2(30);

BEGIN

  l_task := DBMS_SQLTUNE.CREATE_TUNING_TASK(sql_id => '&sql_id');

  DBMS_SQLTUNE.EXECUTE_TUNING_TASK(task_name => l_task);

  DBMS_OUTPUT.PUT_LINE(DBMS_SQLTUNE.REPORT_TUNING_TASK(l_task));

END;

/

 

3.6  Reduce Hard Parsing — Use Bind Variables

Hard parsing consumes CPU and shared pool memory. Ensure applications use bind variables, not literal values:

-- BAD (hard parse on every execution):

SELECT * FROM orders WHERE order_id = 12345;

 

-- GOOD (soft parse on repeated executions):

SELECT * FROM orders WHERE order_id = :order_id;

 

Monitor hard vs. soft parse rates:

SELECT name, value FROM v$sysstat

WHERE  name IN ('parse count (hard)', 'parse count (total)');

 


 

Step 4: Optimize Indexes

 

Correct index strategy eliminates full table scans and reduces I/O dramatically. Oracle 19c supports B-tree, bitmap, function-based, and invisible indexes.

 

4.1  Identify Missing Indexes

Use the AWR SQL report or look for high buffer get SQL. You can also query the SQL Access Advisor:

BEGIN

  DBMS_ADVISOR.QUICK_TUNE(

    advisor_name => DBMS_ADVISOR.SQLACCESS_ADVISOR,

    task_name    => 'idx_advisor_task',

    attr1        => 'SELECT * FROM orders WHERE cust_id = :x'

  );

END;

/

 

4.2  Find Unused Indexes

Unused indexes waste space and slow down DML operations:

SELECT index_name, table_name, monitoring, used

FROM   v$object_usage

WHERE  used = 'NO';

 

Enable monitoring before checking:

ALTER INDEX idx_name MONITORING USAGE;

 

4.3  Rebuild Fragmented Indexes

Check index fragmentation with ANALYZE:

ANALYZE INDEX idx_name VALIDATE STRUCTURE;

SELECT name, del_lf_rows, lf_rows,

       ROUND(del_lf_rows/NULLIF(lf_rows,0)*100,2) AS pct_deleted

FROM   index_stats;

 

Rebuild if pct_deleted exceeds 20%:

ALTER INDEX idx_name REBUILD ONLINE PARALLEL 4;

 

4.4  Use Invisible Indexes for Safe Testing

Test a new index without impacting the current workload:

CREATE INDEX idx_test ON orders(status, created_date) INVISIBLE;

-- Test with optimizer_use_invisible_indexes = TRUE at session level

ALTER SESSION SET optimizer_use_invisible_indexes = TRUE;

 

4.5  Consider Partitioned Indexes for Large Tables

For tables with hundreds of millions of rows, local partitioned indexes align with table partitions and dramatically reduce I/O:

CREATE INDEX idx_orders_date

ON orders (order_date)

LOCAL COMPRESS 1;

 


 

Step 5: Tune I/O and Storage

 

Disk I/O is often the final bottleneck after memory and SQL are optimized. Oracle 19c integrates tightly with ASM (Automatic Storage Management) and supports Smart Flash Cache.

 

5.1  Identify I/O Bottlenecks

SELECT file#, name,

       phyrds, phywrts,

       readtim/NULLIF(phyrds,0) AS avg_read_ms,

       writetim/NULLIF(phywrts,0) AS avg_write_ms

FROM   v$filestat f, v$datafile d

WHERE  f.file# = d.file#

ORDER  BY phyrds + phywrts DESC;

 

5.2  Spread Hot Datafiles Across Disks

Move hot datafiles to separate spindles or SSDs using ASM rebalancing or OS-level file moves:

-- In ASM: rebalance disk group

ALTER DISKGROUP data REBALANCE POWER 4;

 

5.3  Configure db_file_multiblock_read_count

For datawarehouses with many full scans, increase the multiblock read count:

ALTER SYSTEM SET db_file_multiblock_read_count = 128 SCOPE=BOTH;

 

5.4  Monitor and Tune Redo Log I/O

Excessive log switches cause checkpoint storms and I/O spikes:

SELECT sequence#, members, archived,

       (sysdate - first_time)*24*60 AS age_minutes

FROM   v$log

ORDER  BY first_time;

 

Target: redo logs should switch no more than 4-6 times per hour. Increase log file size if switching more frequently:

-- Add new larger log group

ALTER DATABASE ADD LOGFILE GROUP 4

  ('/oradata/redo04a.log', '/oradata/redo04b.log') SIZE 1G;

 

5.5  Enable Direct Path Reads for Large Segments

For parallel query and large table scans, direct path reads bypass the buffer cache and reduce cache pollution:

ALTER SESSION SET "_serial_direct_read" = TRUE;  -- session level testing

 


 

Step 6: Manage Waits and Contention

 

Wait events indicate where sessions are blocked. Understanding the top wait events from AWR guides the next tuning actions.

 

6.1  Categorize Wait Events

 

Wait Event

Meaning & Action

db file sequential read

Single-block I/O — usually index scans. Optimize indexes or add storage speed.

db file scattered read

Multi-block full scans. Consider partitioning or adding indexes.

log file sync

Commits waiting for redo flush. Batch commits, or move redo to faster storage.

library cache lock/pin

Hard parsing or DDL contention. Use bind variables, avoid DDL under load.

buffer busy waits

Hot blocks — multiple sessions reading the same block. Reduce row chaining or use reverse indexes.

enq: TX - row lock contention

Row-level locking conflict. Review application transaction logic and commit frequency.

latch: cache buffers chains

Buffer cache latch — typically caused by hot blocks. Use reverse key indexes or partitioning.

direct path read/write

Parallel query or sort/temp I/O. Check PGA sizing and parallel degree.

 

6.2  Identify Blocking Sessions

SELECT l1.sid AS waiter, l2.sid AS blocker,

       l1.type, l1.id1, l1.id2

FROM   v$lock l1, v$lock l2

WHERE  l1.block  = 0

AND    l2.block  = 1

AND    l1.id1    = l2.id1

AND    l1.id2    = l2.id2;

 

6.3  Reduce Latch Contention

Increase the number of buffer cache chains (requires instance restart) or reduce hot block access patterns:

-- Check latch hit ratio

SELECT name, gets, misses,

       ROUND((1 - misses/NULLIF(gets,0))*100,2) AS hit_pct

FROM   v$latch

WHERE  gets > 0

ORDER  BY misses DESC

FETCH  FIRST 10 ROWS ONLY;

 


 

Step 7: Tune the Oracle Optimizer

 

The Cost-Based Optimizer (CBO) in Oracle 19c is highly sophisticated. Ensuring it has accurate statistics and correct configuration is essential.

 

7.1  Key Optimizer Parameters

 

Parameter

Guidance

optimizer_mode

CHOOSE (default). Use ALL_ROWS for batch/OLAP; FIRST_ROWS_n for OLTP with pagination.

optimizer_features_enable

Should match DB version: '19.1.0'. Never lower this unless debugging a regression.

optimizer_adaptive_plans

TRUE (default in 19c). Allows mid-execution plan switches. Set FALSE if causing instability.

optimizer_adaptive_statistics

FALSE (default in 19c). Enable only if you understand adaptive statistics impact.

optimizer_dynamic_sampling

2 (default). Increase to 4-6 for tables without fresh statistics.

_optimizer_use_feedback

TRUE. Feedback mechanism corrects cardinality errors over repeated executions.

 

7.2  Extended Statistics for Correlated Columns

When the optimizer underestimates cardinality for combined column predicates, create column group statistics:

SELECT DBMS_STATS.CREATE_EXTENDED_STATS(

  ownname => 'SCOTT',

  tabname => 'ORDERS',

  extension => '(STATUS, REGION)'

) FROM DUAL;

 

Then gather stats again:

EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT','ORDERS');

 

7.3  Lock Statistics for Critical Tables

Prevent statistics from changing for tables where a known-good plan is critical:

EXEC DBMS_STATS.LOCK_TABLE_STATS('SCOTT', 'ORDERS');

 

7.4  Use SQL Plan Management (SPM)

SPM captures and stabilizes execution plans, preventing plan regressions after upgrades or stats refreshes:

-- Load plans from cursor cache into SQL Plan Baselines

DECLARE

  l_cnt PLS_INTEGER;

BEGIN

  l_cnt := DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(sql_id => '&sql_id');

  DBMS_OUTPUT.PUT_LINE('Plans loaded: ' || l_cnt);

END;

/

 


 

Step 8: Configure Parallelism

 

Oracle 19c supports intra-operation parallelism for large queries, DML, and DDL. Correct parallelism tuning avoids resource starvation while accelerating long-running operations.

 

8.1  Key Parallel Parameters

 

Parameter

Description

parallel_max_servers

Maximum PX servers. Set to CPU_COUNT x 2 for most systems.

parallel_degree_policy

MANUAL (default), LIMITED, or AUTO. AUTO lets Oracle auto-compute degree.

parallel_min_percent

Minimum % of requested degree; query waits or runs serial if not met. Default 0.

parallel_adaptive_multi_user

TRUE — reduces degree under heavy concurrency to prevent overloading.

parallel_force_local

TRUE in RAC to prevent cross-instance PX traffic (use if RAC interconnect is slow).

 

8.2  Set Parallel Degree on Objects

-- Enable parallel query on a table

ALTER TABLE fact_sales PARALLEL 8;

 

-- Run a specific query in parallel

SELECT /*+ PARALLEL(t,8) */ * FROM fact_sales t

WHERE  region = 'APAC';

 

8.3  Monitor Parallel Execution

SELECT qcsid, server#, degree, req_degree,

       status, last_query

FROM   v$px_session

WHERE  qcsid IS NOT NULL;

 


 

Step 9: Tune Temporary Tablespace and Sorts

 

Disk sorts in the TEMP tablespace indicate insufficient PGA. Excessive TEMP usage causes severe I/O overhead.

 

9.1  Monitor TEMP Usage

SELECT tablespace_name,

       total_blocks * 8192/1024/1024 AS total_mb,

       used_blocks  * 8192/1024/1024 AS used_mb,

       free_blocks  * 8192/1024/1024 AS free_mb

FROM   v$sort_segment;

 

9.2  Identify Sessions Using TEMP

SELECT s.sid, s.username, s.sql_id,

       u.tablespace, u.blocks * 8192/1024/1024 AS mb_used

FROM   v$session s, v$tempseg_usage u

WHERE  s.saddr = u.session_addr

ORDER  BY u.blocks DESC;

 

9.3  Add Temp Space or Increase PGA

If TEMP is exhausted, add a tempfile:

ALTER TABLESPACE temp ADD TEMPFILE '/oradata/temp02.dbf'

SIZE 10G AUTOEXTEND ON NEXT 1G MAXSIZE 50G;

 

Or increase PGA to reduce disk sorts:

ALTER SYSTEM SET pga_aggregate_target = 8G SCOPE=BOTH;

 


 

Step 10: Implement Ongoing Monitoring

 

Tuning is not a one-time exercise. Implement automated monitoring to detect regressions before users report them.

 

10.1  Schedule Regular AWR Reports

Use DBMS_SCHEDULER to generate and email AWR reports nightly:

BEGIN

  DBMS_SCHEDULER.CREATE_JOB(

    job_name   => 'NIGHTLY_AWR_SNAPSHOT',

    job_type   => 'PLSQL_BLOCK',

    job_action => 'DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT();',

    start_date => SYSTIMESTAMP,

    repeat_interval => 'FREQ=HOURLY',

    enabled    => TRUE

  );

END;

/

 

10.2  Configure Oracle Enterprise Manager (OEM)

Oracle 19c integrates with OEM Database Express (free) and OEM Cloud Control (licensed). Key alerts to configure:

       Tablespace usage > 85%

       CPU utilization > 90% sustained for > 5 minutes

       Active sessions > 3x normal baseline

       Response time degradation > 50% from baseline

       Redo log switch frequency > 8 per hour

 

10.3  Key V$ Views for Ongoing Monitoring

 

View

Purpose

V$SESSION

Active/inactive sessions, wait events, SQL being executed.

V$SQLSTATS

Aggregate SQL execution statistics across all cursors.

V$SYSMETRIC

System-level metrics: DB time, CPU, IOPS, buffer cache hit ratio.

V$ACTIVE_SESSION_HISTORY

1-second sampled ASH data — last 1 hour in memory.

DBA_HIST_ACTIVE_SESS_HISTORY

Persisted ASH history in AWR (requires Diagnostics Pack).

V$EVENT_HISTOGRAM

Distribution of wait event duration — useful for latency profiling.

V$OSSTAT

OS-level CPU, memory, and I/O statistics from the OS layer.

 

10.4  Health Monitor Checks

Oracle 19c includes built-in Health Monitor checks. Run a comprehensive health check:

BEGIN

  DBMS_HM.RUN_CHECK(

    check_name => 'DB Structure Integrity Check',

    run_name   => 'manual_health_check'

  );

END;

/

 

View results:

SELECT run_id, name, status, start_time, end_time

FROM   v$hm_run

ORDER  BY start_time DESC;

 


 

Quick Reference: Tuning Checklist

 

 

Pre-Tuning Checklist

1.    Enable AWR with 60-minute interval and 30-day retention

2.    Take baseline AWR snapshot before and after peak load

3.    Generate and analyze AWR + ADDM reports

4.    Review ASH for top wait events over last 24 hours

5.    Identify top 10 SQL by elapsed time and buffer gets

 

Memory Tuning Checklist

6.    Verify buffer cache hit ratio > 99%

7.    Check shared pool free memory > 10% of total

8.    Confirm PGA aggregate target is 20-25% of available RAM

9.    Review SGA dynamic component history for auto-tuning accuracy

 

SQL Tuning Checklist

10.  Capture actual execution plans for top 10 SQL

11.  Check for full table scans on large tables

12.  Verify statistics are less than 7 days old on critical tables

13.  Run SQL Tuning Advisor on high-load SQL IDs

14.  Confirm application uses bind variables — no literal SQL

 

Index Checklist

15.  Identify and drop unused indexes (after monitoring > 7 days)

16.  Rebuild indexes with > 20% deleted leaf rows

17.  Add missing indexes identified by explain plan analysis

18.  Verify composite indexes match query predicate column order

 

I/O Checklist

19.  Identify hottest datafiles by physical reads/writes

20.  Verify redo log switches < 4-6 per hour

21.  Check TEMP tablespace utilization and add space if > 80%

22.  Confirm ASM disk groups are balanced

 

 

End of Oracle 19c Performance Tuning Guide

Refer to Or