What you’ll learn
Use this as your checklist. This page is intentionally “study-friendly”: you can tick items as you learn.
2026 version snapshot (quick)
As of Oracle’s published Lifetime Support chart: 19c is the long-term release with premier support through 2029 and extended support through 2032. 21c is an innovation release (premier support through 2027). 26ai is listed as a long-term release with premier support through 2031. 11g/12c releases are out of extended support.
The step-by-step workflow
Use this during incidents. The goal is to avoid “random tuning” and always keep evidence.
- Define the goal and scope
Is it response time or throughput? Is it system-wide, service-wide, or only one SQL statement? Write down the target (example: “p95 from 2.4s → 500ms”). - Measure DB time first
DB time is your master metric (CPU + non-idle waits for active sessions). If DB time spikes, you must identify which wait class/event or CPU dominates. - Find the biggest contributors
Identify top SQL (by DB time / CPU / elapsed time) and top wait events during the “bad window”. Fixing the top 1–5 SQLs often beats micro-optimizing everything. - Pick the right drill tool
Now: SQL Monitor / Real-Time Monitoring. History: AWR/ADDM. No packs: SQL Trace + TKPROF. - Confirm the actual plan
Avoid EXPLAIN PLAN-only tuning when possible. Prefer cursor-cache plan with row counts: compare E-Rows vs A-Rows per step. - Diagnose root cause by category
Common categories: inefficient SQL shape, missing/stale stats, missing access path, plan regression, parsing storms, locking. - Apply the smallest safe fix
Prefer: fix stats → add index (if needed) → rewrite SQL → plan stability (SPM/profile/patch) → hints (last resort). - Validate and prevent regression
Re-measure DB time and statement time. If plan changed or improved, consider plan baselines for stability.
Fast triage cheat sheet
CPU-bound
You see high DB CPU / “on CPU” activity. Typical causes: inefficient SQL (too many rows), missing access paths, bad join order, parsing storms.
Action: identify top SQL by CPU/DB time → SQL Monitor + plan stats → reduce work.
I/O-bound
Dominant I/O wait class/events, high reads, long I/O time. Typical causes: full scans, missing indexes, poor clustering, storage latency.
Action: identify top SQL → verify access path → index/partition/rewrite.
Concurrency / locking
Many sessions waiting on locks/latches or “blocking session” dominates.
Action: find blockers, shorten transactions, reduce hot rows, review app transaction design.
Parsing / shared pool pressure
Excessive hard parses, many similar SQLs differing by literals/formatting.
Action: enforce bind variables + consistent SQL text; avoid CURSOR_SHARING=FORCE as a permanent fix.
✨ Ask AI: Oracle Error or Wait Event
Stuck on a weird wait event or an ORA- code? Let the Gemini Assistant explain it and suggest triage steps.
Mini glossary: DB time, waits, AAS
DB time = CPU time + non-idle wait time across active sessions (cumulative).
Wait event = what a session is waiting for (I/O, locks, etc.).
Average Active Sessions (AAS) is a convenient way to visualize how much work and waiting happens over time, broken down by dimensions like SQL ID or wait class.
Execution plans (done right)
Execution plans are your “X-ray”. But you must prefer actual execution statistics over purely explained plans.
✨ AI Plan Analyzer
Paste your raw DBMS_XPLAN or EXPLAIN PLAN output. Gemini will identify bottlenecks like unexpected full scans, Cartesian joins, or bad cardinality estimates.
Copy‑paste starter: show plan with actual row counts (when available)
-- 1) Run the statement with plan statistics enabled (example)
-- You may need: ALTER SESSION SET statistics_level = ALL;
SELECT /*+ gather_plan_statistics */ ...
FROM ...
WHERE ...;
-- 2) Display plan from cursor cache with actual stats
SELECT * FROM TABLE(
DBMS_XPLAN.DISPLAY_CURSOR(
NULL, NULL, 'TYPICAL +ALLSTATS LAST'
)
);
How to interpret the “E-Rows vs A-Rows” mismatch
If the optimizer estimated 10 rows (E-Rows) but you actually got 100,000 (A-Rows), the plan choice can easily be wrong (nested loop vs hash join, index vs full scan). Common suspects: stale stats, skew/histograms, bind peeking/cursor sharing effects.
SQL Rewriting & Optimization
Sometimes the best way to fix a performance issue is to stop relying on the optimizer to rescue bad code, and rewrite the query to remove anti-patterns.
✨ AI SQL Optimizer
Paste a slow or inefficient SQL query. Gemini will analyze it for anti-patterns (like implicit conversions, non-sargable predicates, or correlated subqueries) and suggest an optimized rewrite.
Advanced indexing techniques
Index type selection (quick rules)
- B-tree: Most OLTP workloads (high concurrency, selective predicates).
- Bitmap: Mainly data warehousing / low-cardinality columns, but can be risky with OLTP DML concurrency.
- Function-based: When your predicate uses an expression (e.g.,
UPPER(col)).
Function‑based index example
-- If your queries do: WHERE UPPER(email) = :email
-- then a normal index on email may not be used.
-- A function-based index can help:
CREATE INDEX users_email_u_idx ON users (UPPER(email));
Invisible-index testing (safe experimentation)
For safer index experiments, you can create an index as INVISIBLE (so it won’t be used unless you explicitly allow it), test it, then decide whether to make it visible. This is a strong strategy for avoiding surprise regressions.
✨ AI Indexing Advisor
Not sure what index to build? Paste your table columns and the slow query, and Gemini will suggest the optimal index type (and provide the DDL).
Optimizer statistics
Automatic optimizer statistics collection (concept)
In modern Oracle versions, automatic statistics tasks are designed to refresh objects whose stats are missing or stale. That reduces risk of bad plans from outdated inputs.
DBMS_STATS: a safe “starter” command (table-level)
-- Example: gather stats for one table (adjust options for your environment)
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(
ownname => 'APP',
tabname => 'ORDERS',
cascade => TRUE
);
END;
/
When to be careful
Statistics changes can change execution plans. That can be good (fix regressions) or risky (create regressions). When performance is mission-critical, capture “before”, make a targeted stats change, and validate “after”.
Cursor sharing & bind variables
Cursor sharing can improve performance dramatically by reducing hard parses and enabling plan reuse, but it requires discipline in SQL text consistency and bind usage.
Developer checklist
Plan stability tools
When a plan change causes a regression, you often need a controlled mechanism that keeps performance stable while the environment evolves.
SQL Plan Management
Use SQL plan baselines so the optimizer uses only accepted/verified plans. Ideal for preventing regressions after upgrades or statistics shifts.
SQL Profiles / SQL Patches
Profiles improve estimates; patches apply targeted optimizer directives (hints) without changing the app SQL. Use governance: track why it exists and when to remove it.
Hints: when to use (and when not to)
Hints are useful for controlled testing and quick experiments, but they create “extra code to manage” and can become wrong as data changes. Prefer plan management tools for long-term stability.
Toolbelt
SQL Monitor report: generate HTML
-- Example (requires proper licensing / pack enablement):
-- Generate an SQL Monitor report as HTML for a SQL_ID
SET PAGESIZE 0
SET LINESIZE 32767
SET LONG 5000000
SET LONGCHUNKSIZE 5000000
SPOOL sqlmon_report.html
SELECT DBMS_SQL_MONITOR.REPORT_SQL_MONITOR(
sql_id => 'your_sql_id_here',
type => 'HTML',
report_level => 'ALL'
)
FROM dual;
SPOOL OFF
SQL Trace + TKPROF (no-pack fallback)
-- Session-level SQL trace (example)
EXEC DBMS_SESSION.SET_SQL_TRACE(TRUE);
-- Run your workload here...
EXEC DBMS_SESSION.SET_SQL_TRACE(FALSE);
-- Then run TKPROF on the generated trace file (OS command)
-- tkprof input.trc output.txt sort=exeela
✨ AWR / Statspack Summarizer
AWR reports can be overwhelming. Paste the "Top 10 Foreground Events" or "SQL ordered by Elapsed Time" text snippet here for a plain-English executive summary.
✨ Diagnostic Script Generator
Describe a DBA task in plain English (e.g., "Find all blocking sessions" or "Show tablespace usage"), and Gemini will write the Oracle SQL script for you.
Practice labs
Lab: Find top SQL and pick one target
Goal: Learn how to choose what to tune first.
- Pick a known “bad window” (a slow period).
- Identify top SQL by DB time / AAS.
- Select one statement with high DB time and clear business impact.
- Collect: SQL text, SQL_ID, plan hash value, basic runtime metrics.
Lab: Diagnose an E‑Rows vs A‑Rows mismatch
Goal: Learn how to spot bad estimates and what usually fixes them.
- Get the actual plan with statistics (ALLSTATS LAST).
- Highlight the first plan step where A-Rows diverges massively from E-Rows.
- Hypothesis: stale stats or skew/histograms.
- Apply a targeted stats refresh, then re-run and compare.
Weekly quizzes
Quiz: Why is EXPLAIN PLAN not enough?
Answer key: EXPLAIN PLAN shows what the optimizer would do in the explain environment, which can differ from execution, so the explained plan can differ from the actual plan. Always validate with runtime evidence when possible.
Quiz: What is DB time, in one sentence?
Answer key: DB time is the sum of CPU time and non-idle wait time across all active sessions (cumulative).
Quiz: Why can two queries that “look the same” fail to share a cursor?
Answer key: Cursor sharing requires character-for-character identical SQL text (including spaces/case/comments), plus compatible optimizer environment and other checks.
References (primary starting points)
These are the core docs that back the methodology in this post.
- Oracle Lifetime Support Policy — Coverage for Technology (support dates table)
- Oracle Database Licensing Information User Manual (Diagnostics/Tuning pack requirements)
- Oracle SQL Tuning Guide (26ai) — methodology, tools, optimizer controls
- AWR documentation (what it collects and why)
- Monitoring Database Operations / SQL Monitor documentation
- Execution plans documentation (EXPLAIN PLAN vs actual plans, DBMS_XPLAN)
- Indexes & index-organized tables documentation