Tuesday, May 26, 2026

Approach to correlate AWR + iostat to deep drive and troubleshoot oracle database performance issue

 

✅ 1. Objective

๐Ÿ‘‰ Correlate:

  • OS layer → iostat (disk bottleneck)
  • DB layer → AWR (SQL causing I/O)

๐Ÿ‘‰ Goal: Identify which SQL caused the spike on dm- disks*


๐Ÿง  ✅ 2. Correlation Logic (Core Concept)

Disk spike (iostat)
      ↓
Time window
      ↓
AWR snapshot
      ↓
Top IO SQL
      ↓
Execution plan
      ↓
Root cause

⏱️ ✅ 3. STEP 1: Identify Spike Time from iostat

Example:

dm-69 → 100% util
await → 97 ms

๐Ÿ‘‰ Note:

  • Exact time window (e.g.)
10:02 AM – 10:10 AM

๐Ÿ“Š ✅ 4. STEP 2: Find Matching AWR Snapshot

SELECT snap_id, begin_interval_time, end_interval_time
FROM dba_hist_snapshot
ORDER BY snap_id DESC;

๐Ÿ‘‰ Pick snapshots covering spike:

Snap 101 → 10:00
Snap 102 → 10:10

๐Ÿ”ฅ ✅ 5. STEP 3: Identify Top SQL by I/O

✅ Query 1: Top Disk Read SQL

SELECT *
FROM (
SELECT
sql_id,
executions_delta,
disk_reads_delta,
buffer_gets_delta,
elapsed_time_delta/1000000 elapsed_sec,
ROUND(disk_reads_delta/DECODE(executions_delta,0,1,executions_delta)) reads_per_exec
FROM dba_hist_sqlstat
WHERE snap_id BETWEEN :snap1 AND :snap2
ORDER BY disk_reads_delta DESC
)
WHERE ROWNUM <= 10;


✅ Query 2: Top Read Throughput

SELECT *
FROM (
SELECT
sql_id,
disk_reads_delta,
buffer_gets_delta,
rows_processed_delta,
elapsed_time_delta/1000000 elapsed_sec
FROM dba_hist_sqlstat
WHERE snap_id BETWEEN :snap1 AND :snap2
ORDER BY disk_reads_delta DESC
)
WHERE ROWNUM <= 10;


✅ Query 3: Full Table Scan Candidates

SELECT sql_id,
disk_reads_delta,
executions_delta,
ROUND(disk_reads_delta/DECODE(executions_delta,0,1,executions_delta)) reads_per_exec
FROM dba_hist_sqlstat
WHERE snap_id BETWEEN :snap1 AND :snap2
AND disk_reads_delta > 100000
ORDER BY disk_reads_delta DESC;


๐Ÿ” ✅ 6. STEP 4: Identify Wait Events

SELECT event, total_waits_delta, time_waited_delta/1000 time_waited_ms
FROM dba_hist_system_event
WHERE snap_id BETWEEN :snap1 AND :snap2
AND event LIKE 'db file%'
ORDER BY time_waited_ms DESC;


✅ Interpretation:

Wait EventMeaning
db file scattered readFull table scan ๐Ÿšจ
db file sequential readIndex access
direct path readBig scans (DW)
db file parallel readParallel scans

๐Ÿ“ˆ ✅ 7. STEP 5: Map SQL → Execution Plan

SELECT *
FROM dba_hist_sql_plan
WHERE sql_id = '&sql_id'
ORDER BY id;

✅ Look for:

  • TABLE ACCESS FULL ๐Ÿšจ
  • INDEX RANGE SCAN
  • FULL OUTER JOIN
  • Parallel operations

๐Ÿ”— ✅ 8. STEP 6: Correlate with Disk Pattern


๐Ÿ”ด Case 1 (Your Earlier Example)

iostat:
avgrq-sz ~ 1024 KB
high rMB/s
high await

๐Ÿ‘‰ AWR shows:

db file scattered read
direct path read

✅ Conclusion: Large full table scans causing disk saturation


๐ŸŸข Case 2

small avgrq-sz
high IOPS
low await

๐Ÿ‘‰ AWR:

db file sequential read

✅ Conclusion: Healthy OLTP workload


๐Ÿงช ✅ 9. Advanced Correlation Query (BEST ONE)


SELECT
s.sql_id,
t.sql_text,
s.executions_delta,
s.disk_reads_delta,
ROUND(s.disk_reads_delta/DECODE(s.executions_delta,0,1,s.executions_delta)) reads_per_exec,
s.elapsed_time_delta/1000000 elapsed_sec
FROM dba_hist_sqlstat s,
dba_hist_sqltext t
WHERE s.sql_id = t.sql_id
AND s.snap_id BETWEEN :snap1 AND :snap2
ORDER BY s.disk_reads_delta DESC
FETCH FIRST 10 ROWS ONLY;


๐ŸŽฏ ✅ 10. Root Cause Identification Matrix

iostat PatternAWR FindingRoot Cause
Large IO + high latencyscattered readFull table scan
High read MB/sdirect path readLarge query
High write latencylog file syncCommit bottleneck
High queuemany active sessionsConcurrency overload

๐Ÿšจ ✅ 11. Real Example (Like Your Case)

iostat

%util = 100
await = 97 ms
avgqu-sz = 24
rMB/s = high

AWR

Event: db file scattered read
SQL_ID: abc123xyz
Disk Reads: very high
Plan: TABLE ACCESS FULL

✅ FINAL ROOT CAUSE

๐Ÿ‘‰ A large SQL doing full table scan
๐Ÿ‘‰ Saturating disk -> causing high latency


✅ ✅ 12. Fix Strategy

✅ SQL Level

  • Add indexes
  • Rewrite query
  • Avoid full scans

✅ DB Level

  • Increase buffer cache
  • Enable parallel limits

✅ Storage Level

  • Spread datafiles
  • Use faster disk tier

✅ ✅ 13. Ultimate One-Liner Workflow (Production)

iostat spike → note time
→ find AWR snapshot
→ find top IO SQL
→ check wait events
→ review execution plan
→ fix SQL

Storage Disk Performance Baseline Table to troubleshoot the performance issue

 

Disk Performance Baseline Table (iostat -xm)

๐Ÿ“Š 1. Latency (Most Important)

MetricGood ✅Warning ⚠️Critical ๐ŸšจNotes
await (ms)< 55 – 20> 50Total latency (queue + service)
r_await< 55 – 20> 50Read latency
w_await< 55 – 20> 50Write latency

๐Ÿ“Š 2. Disk Utilization

MetricGood ✅Warning ⚠️Critical ๐ŸšจNotes
%util< 70%70–90%> 90%High alone is OK if latency is low

๐Ÿ“Š 3. Queue Depth (Pressure Indicator)

MetricGood ✅Warning ⚠️Critical ๐ŸšจNotes
avgqu-sz< 11 – 5> 10Queue waiting to be served

๐Ÿ“Š 4. Service Time vs Wait Time

PatternInterpretation
await ≈ svctm✅ Healthy (no queueing)
await >> svctm๐Ÿšจ Queue bottleneck

๐Ÿ“Š 5. Throughput (rMB/s, wMB/s)

For modern systems (SSD / SAN / NVMe)

MetricGood ✅Warning ⚠️Critical ๐Ÿšจ
Read throughput< 70% of max capacity70–90%> 90% sustained
Write throughputSame as aboveSameSame

๐Ÿ‘‰ Absolute value depends on storage type:

  • HDD: ~100–200 MB/s
  • SSD: ~500 MB/s – 2 GB/s
  • NVMe: 2–5+ GB/s

๐Ÿ“Š 6. IOPS (r/s, w/s)

WorkloadTypical Healthy Range
OLTP (random IO)1K – 50K IOPS
DW / AnalyticsLower IOPS, higher throughput

๐Ÿ‘‰ Key rule:

  • High IOPS + low latency = ✅ good
  • High IOPS + high latency = ๐Ÿšจ bottleneck

๐Ÿ“Š 7. IO Size (avgrq-sz)

ValueMeaningHealth
< 32 KBRandom IO (OLTP)
64–256 KBMixed
~512 KB – 1 MBSequential scan⚠️ if causing latency

๐ŸŽฏ ✅ Quick Decision Matrix

ConditionVerdict
High %util + low await (<5ms)✅ Healthy
High %util + high await (>50ms)๐Ÿšจ Bottleneck
High queue (>10)๐Ÿšจ Overloaded
Low util + high await⚠️ Storage issue
Large IO + high latency⚠️ Scan / DW workload

๐Ÿ“Œ ✅ DBA-Focused Interpretation

PatternRoot Cause
High rMB/s + large avgrq-szFull table scans
High r/s + small IOIndex access
High w_awaitLog/write issue
High avgqu-szStorage saturation
High await everywhereStorage slow

๐Ÿ”ฅ ✅ Golden Rules (Use in Production)

✅ Healthy Disk

%util < 80
await < 10 ms
avgqu-sz < 3

⚠️ Warning Zone

%util > 80
await 10–30 ms
avgqu-sz 3–10

๐Ÿšจ Critical Disk Bottleneck

%util > 90
await > 50 ms
avgqu-sz > 10
await >> svctm

✅ ✅ Example Applied to Your Earlier Data

DiskVerdict
dm-xx (await ~97 ms, util 100%)๐Ÿšจ Critical
dm-xxx (queue 40, await 72 ms)๐Ÿšจ Severe
dm-xxx (await 1.5 ms, util 99%)✅ Healthy

Save as disk_health_score.sh

#!/bin/bash

echo "===== Disk Health Score ====="
date
echo ""

iostat -xm 2 3 | awk '

function score(util, await, queue) {
    s = 100

    # Util penalty
    if (util > 90) s -= 25
    else if (util > 70) s -= 10

    # Await penalty
    if (await > 50) s -= 50
    else if (await > 20) s -= 30
    else if (await > 5) s -= 15

    # Queue penalty
    if (queue > 10) s -= 40
    else if (queue > 5) s -= 20
    else if (queue > 1) s -= 10

    if (s < 0) s = 0
    return s
}

function status(s) {
    if (s >= 80) return "HEALTHY"
    else if (s >= 60) return "WARNING"
    else if (s >= 40) return "DEGRADED"
    else return "CRITICAL"
}

/Device/ {
    printf "%-10s %-6s %-8s %-8s %-6s\n","Device","Util%","Await","Queue","Status"
    next
}

$1 ~ /^(sd|dm)/ {
    util = $NF
    await = $(NF-3)
    queue = $(NF-4)

    s = score(util, await, queue)
    st = status(s)

    printf "%-10s %-6.1f %-8.1f %-8.1f %-6s\n",$1,util,await,queue,st
}
'

chmod +x disk_health_score.sh
./disk_health_score.sh

Sample Output 

Device     Util%  Await    Queue    Status
dm-xx      100.0  97.2     24.3     CRITICAL
dm-xxx     99.9   72.4     40.5     CRITICAL
dm-xx      99.9   80.0     7.2      DEGRADED
dm-xxx     99.4   1.5      11.6     WARNING

Map Actual storage disk mount point to troubleshoot the storage related performance issue

 

๐Ÿ”— 1. Map dm-* → Actual Mount Points (VERY IMPORTANT)

✅ Command:

lsblk -o NAME,KNAME,MOUNTPOINT,SIZE,FSTYPE | grep dm-

✅ If using LVM:

dmsetup ls --tree

✅ Detailed mapping:

lsblk -o NAME,KNAME,PKNAME,MOUNTPOINT | column -t

✅ Correlate with filesystem:

df -h | grep /dev/mapper

๐Ÿ‘‰ Why this matters

  • dm-62 → logical volume → mount point → DB datafile location
  • Helps answer:

    “Which tablespace is causing this spike?”


๐Ÿ”— 2. Map Disk → Oracle / DB Files

✅ For Oracle:

SELECT file_name, tablespace_name
FROM dba_data_files
WHERE file_name LIKE '%<mount_point>%';

✅ Check temp / redo:

SELECT name FROM v$tempfile;
SELECT member FROM v$logfile;

๐Ÿ‘‰ Now you can map:

dm-69 → /u02 → USERS tablespace → full scan

๐Ÿ“Š 3. iostat → DB Wait Event Mapping

iostat PatternDB Wait EventMeaning
High rMB/s + large avgrq-szdb file scattered readFull table scan
High r/s small IOdb file sequential readIndex lookup
High w_awaitlog file syncCommit latency
High avgqu-szfree buffer waitsDB buffer pressure
High awaitAny IO waitStorage slow

๐Ÿšจ 4. Alert Thresholds (Production Standard)

✅ Disk Health Thresholds

MetricWarningCritical
%util>80%>90%
await>20 ms>50 ms
avgqu-sz>5>10
svctm vs await gapnoticeablelarge gap

✅ Quick Alert Command

iostat -xm 2 5 | awk '
/Device/ {print; next}
$1 ~ /^(sd|dm)/ && ($NF > 90 || $10 > 50 || $9 > 10) {print}
'

๐Ÿ‘‰ Triggers when:

  • %util > 90
  • await > 50 ms
  • queue > 10

๐Ÿ“ˆ 5. Real-Time Monitoring Script (Reusable)

✅ Save as disk_monitor.sh

#!/bin/bash

echo "==== Disk Bottleneck Check ===="
date

iostat -xm 2 3 | awk '
/Device/ {print; next}
$1 ~ /^(sd|dm)/ && ($NF > 90 || $10 > 50 || $9 > 10) {
printf "ALERT: %-8s util=%s%% await=%sms queue=%s\n", $1, $NF, $10, $9
}'


✅ Run:


chmod +x disk_monitor.sh
./disk_monitor.sh


๐Ÿ” 6. Identify Top IO Consumers

✅ Process level:

iotop -oP

✅ File level:

lsof | grep <device>

✅ Per process IO:

pidstat -d 2

๐Ÿง  7. Advanced DBA Analysis Flow

When you see:

%util = 100
await = high
avgqu-sz = high

✅ Follow this sequence:

  1. Identify disk
  2. Map to mount point
  3. Map to DB file
  4. Identify SQL causing IO
  5. Check execution plan

⚡ 8. Quick Root Cause Patterns

๐Ÿ”ด Pattern 1 (Your case earlier)

avgrq-sz ~ 1024 KB
await ~ 80–100 ms

๐Ÿ‘‰ Cause:

  • Full table scans
  • Data warehouse queries

๐ŸŸข Pattern 2

r/s high + avgrq-sz small + low await

๐Ÿ‘‰ Cause:

  • OLTP workload (healthy)

๐Ÿ”ด Pattern 3

w_await high

๐Ÿ‘‰ Cause:

  • Commit issues
  • Log sync bottleneck

๐ŸŽฏ 9. What You Should Do Immediately (From Your Data)

Based on your earlier output:

๐Ÿšจ Critical disks:

  • dm-69
  • dm-275

✅ Action Plan:

  1. Map these disks → mount point
  2. Identify DB objects
  3. Run:
SELECT sql_id, executions, disk_reads
FROM v$sql
ORDER BY disk_reads DESC FETCH FIRST 10 ROWS ONLY;


✅ Final Takeaway

You now have:

✅ Disk → Mount → DB mapping
✅ Alert thresholds
✅ Real-time monitoring script
✅ DB wait correlation
✅ Troubleshooting workflow

iostat linux command deep drive to troubleshooting the performance issue

  iostat -xm 2 5 | awk '$1 ~ /^(sd|dm)/ && $NF > 40 {printf "%-10s %s\n",$1,$NF"%"}'

 iostat -xm 2 5 | awk '$NF > 40 {print}'

 iostat -xm 2 5 | awk '/Device/ {print; next}$1 ~ /^(sd|dm)/ && $NF > 90 {print}'


๐Ÿ“Œ Header Breakdown (Deep Explanation)

Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util

✅ 1. Device

  • Logical or physical disk name
    • sdX → physical disks
    • dm-X → device mapper (LVM, ASM, multipath)

๐Ÿ‘‰ In your case:

  • dm-* = logical volumes / DB storage layers

✅ 2. rrqm/s (Read Requests Merged per second)

  • Number of read requests merged by OS scheduler

Why merging matters:

  • OS combines adjacent reads to reduce I/O calls

๐Ÿ‘‰ Example:

  • 10 small reads → merged → 1 large read

Interpretation:

  • High value → efficient sequential I/O
  • Zero → either random I/O or already optimized

✅ 3. wrqm/s (Write Requests Merged per second)

  • Same as above but for writes

✅ High value:

  • Good for sequential writes (e.g., redo logs, batch loads)

✅ 4. r/s (Reads per second)

  • Number of read I/O operations per second

Interpretation:

  • High r/s = high IOPS (random access likely)

✅ 5. w/s (Writes per second)

  • Number of write operations per second

๐Ÿ‘‰ Together with r/s:

  • Indicates workload type:
    • OLTP → high r/s + w/s, small IO
    • Analytics → lower r/s but large I/O size

✅ 6. rMB/s (Read throughput in MB/sec)

  • Total data read per second

✅ 7. wMB/s (Write throughput in MB/sec)

  • Total data written per second

๐Ÿ”Ž Important:

PatternMeaning
High r/s + low rMB/ssmall random IO
Low r/s + high rMB/slarge sequential IO

✅ 8. avgrq-sz (Average Request Size)

  • Average size of each I/O request (in KB)

Formula:

avgrq-sz = (total sectors read+written) / total I/O ops

Interpretation:

ValueMeaning
< 32 KBrandom IO (OLTP)
64–256 KBmixed
~1024 KB (1MB)sequential scan

✅ 9. avgqu-sz (Average Queue Length)

  • Number of I/O requests waiting in queue

๐Ÿšจ Critical metric:

ValueImpact
< 1healthy
1–5moderate
10+pressure
20+severe bottleneck

๐Ÿ‘‰ High value means:

  • Disk is overloaded
  • Requests are waiting → latency increase

✅ 10. await (Average Wait Time in ms)

  • Total time for I/O request:
    wait time = queue time + service time
    

๐Ÿšจ Thresholds:

ValueMeaning
< 5 msexcellent
5–20 msacceptable
20–50 mswarning
> 50 msserious issue

๐Ÿ‘‰ This is the most important latency metric


✅ 11. r_await (Read latency)

  • Avg time for read requests

✅ 12. w_await (Write latency)

  • Avg time for write requests

Why split matters:

  • Helps identify:
    • read-heavy issues (full scan)
    • write bottlenecks (redo/log/file sync)

✅ 13. svctm (Service Time)

  • Time taken by disk to service request
  • Does NOT include queue time

Important:

await ≈ svctm + queue delay

Interpretation:

CaseMeaning
await ≈ svctmno queue bottleneck
await >> svctmqueue contention

๐Ÿ‘‰ This is key for bottleneck detection


✅ 14. %util (Utilization)

  • Percentage of time disk was busy

๐Ÿšจ Interpretation:

ValueMeaning
< 60%safe
60–80%moderate
80–90%high
> 90%saturated

๐Ÿ‘‰ BUT:

  • Must combine with await + queue

๐Ÿ”ฅ Important Combined Interpretation

✅ Case 1 (Healthy high usage)

%util = 95%
await = 1 ms
avgqu-sz = 1

✔ Efficient disk


๐Ÿšจ Case 2 (Bottleneck)

%util = 99%
await = 80 ms
avgqu-sz = 20

❌ Disk saturation + queue buildup


๐Ÿง  How You Should Read Header (DBA Cheat Sheet)

Step-by-step analysis:

  1. Check %util

    • 90 → possible saturation

  2. Check avgqu-sz

    • High → queue backlog
  3. Check await

    • Confirms latency impact
  4. Compare await vs svctm

    • Big gap → queue delay
  5. Check avgrq-sz

    • Understand workload type

๐ŸŽฏ Why This Matters for You (Database Architect)

This header directly helps identify:

✅ DB Issues Mapping

MetricDB Problem
High rMB/s + large avgrq-szfull table scan
High r/s, low sizeindex lookup
High w_awaitcommit / redo issues
High avgqu-szstorage contention
High awaitslow queries

✅ Final Summary

  • r/s, w/s → IOPS
  • rMB/s, wMB/s → throughput
  • avgrq-sz → IO size (random vs sequential)
  • avgqu-sz → pressure indicator ๐Ÿšจ
  • await → real latency ๐Ÿšจ
  • %util → saturation signal

Setup and design database architecture to meet SLA - 99.9 , 99.99 , 99.999

Achieving distinct Service Level Agreements (SLAs) for a database requires scaling redundancy and infrastructure complexity.  The three-nine...