What Is the Oracle Optimizer?
Simple Definition (Interview‑Friendly)
The Oracle Optimizer is a component of the Oracle Database that determines the most efficient execution plan for a SQL statement by evaluating different access paths and operations.
In short:
- You write SQL
- Oracle decides how to execute it
- The optimizer makes that decision
Why the Optimizer Is Important
The same SQL statement can be executed in many different ways, for example:
- Full table scan vs index scan
- Nested loop join vs hash join
- Different join orders
The optimizer’s job is to choose the plan with the lowest cost (fastest and least resource‑consuming).
🔑 Performance in Oracle depends more on the optimizer than on the SQL syntax itself.
Types of Oracle Optimizers
1️⃣ Rule‑Based Optimizer (RBO) ⚠️ Obsolete
- Uses predefined rules (e.g., “use index if available”)
- Does not consider data volume or statistics
- Deprecated since Oracle 10g
❌ No longer used in modern Oracle databases
2️⃣ Cost‑Based Optimizer (CBO) ✅ Current
- Uses statistics to estimate cost
- Chooses the most efficient execution plan
- Fully automatic and intelligent
✅ All modern Oracle databases use CBO
How the Cost‑Based Optimizer (CBO) Works
Step‑by‑Step Flow
- Parse SQL statement
- Check for syntax and semantic errors
- Generate multiple possible execution plans
- Estimate cost for each plan
- Select the plan with the lowest cost
- Execute the chosen plan
What Does “Cost” Mean?
Cost is not time.
It is an internal unit based on:
- I/O operations
- CPU usage
- Memory usage
- Data volume
Lower cost ≈ Better plan
Key Inputs Used by the Optimizer
1️⃣ Statistics (Most Important)
Collected using:
DBMS_STATS.GATHER_TABLE_STATS
Optimizer uses stats such as:
- Number of rows
- Number of blocks
- Column selectivity
- Data distribution (histograms)
❌ Wrong statistics → Wrong execution plan
2️⃣ Indexes
- Availability and type of index
- Index selectivity
- Clustering factor
Optimizer decides:
- Whether to use an index
- Which index to use
3️⃣ SQL Predicates
Examples:
Highly selective predicates favor: ✅ Index scans
4️⃣ Join Methods
Optimizer chooses between:
- Nested Loop Join
- Hash Join
- Sort Merge Join
Choice depends on:
- Data size
- Join condition
- Available memory
5️⃣ Optimizer Parameters
Examples:
optimizer_modeoptimizer_index_cost_adjoptimizer_features_enable
DBAs can influence behavior but should not micromanage unless needed.
Common Access Paths Chosen by Optimizer
| Access Path | When Used |
|---|---|
| Full Table Scan | Large data, low selectivity |
| Index Range Scan | Moderate selectivity |
| Index Unique Scan | Primary key lookup |
| Fast Full Index Scan | Index covers all data |
| Bitmap Index Scan | Low cardinality columns |
Execution Plan
The optimizer produces an execution plan, which shows:
- Step‑by‑step operations
- Access paths
- Join order
- Estimated cost
View it using:
SQL
EXPLAIN PLAN
DBMS_XPLAN.DISPLAY
Optimizer Hints
Hints are suggestions, not commands.
Example:
SELECT /*+ INDEX(emp emp_idx) */ * FROM emp WHERE empno = 100;
✅ Used when optimizer chooses a suboptimal plan
❌ Overuse leads to maintenance trouble
🔑 The best practice is to fix statistics or SQL, not force hints.
Bind Variables and Optimizer
- Optimizer may peek at bind values
- Can lead to:
- Bind peeking issues
- Different optimal plans for different values
Modern Oracle versions use:
- Adaptive plans
- Baselines
- SQL plan management
Adaptive Optimizer (Advanced Concept)
Oracle can:
- Change join methods during execution
- Correct bad estimates dynamically
This improves performance in:
- Dynamic workloads
- Skewed data distributions
Optimizer vs DBA (Responsibility Split)
| Optimizer | DBA |
|---|---|
| Chooses execution plan | Provides correct statistics |
| Decides join methods | Designs indexes |
| Estimates cost | Manages parameters |
| Adapts at runtime | Monitors performance |
✅ DBAs enable the optimizer; they don’t replace it.
Common Statements (Interview One‑Liners)
- “Optimizer determines how SQL is executed.”
- “CBO chooses the lowest‑cost plan using statistics.”
- “Bad plans are caused by bad statistics, not bad SQL.”
- “Hints should be the last option.”
Final One‑Line Summary ⭐
The Oracle Optimizer is the intelligence engine of the database that analyzes SQL statements and chooses the most efficient execution plan based on statistics, indexes, and system resources.
1️⃣ Why Oracle Chooses Full Table Scan Instead of Index
This is one of the most misunderstood topics.
Common Myth
“If an index exists, Oracle must use it.”
❌ Wrong
When Oracle Chooses a Full Table Scan (FTS)
Oracle may choose an FTS when:
✅ Large Percentage of Rows Needed
If:
- Table has 1,000,000 rows
- Predicate returns 800,000 rows
➡ Using an index would mean:
- Index scan + table access for each row
- More random I/O
✅ FTS is cheaper
✅ Small Table
If the table fits in a few blocks:
- Reading full table is faster than using index
- Less CPU and latch overhead
✅ Poorly Selective Index
Example:
gender = 'M'
If 90% rows = 'M':
- Index is almost useless
- Optimizer prefers FTS
✅ Clustering Factor Is Bad
- Index rows scattered across table blocks
- Many random I/Os
- FTS is sequential → faster
✅ Parallel Query Enabled
FTS works very efficiently with parallelism.
✅ Outdated or Wrong Statistics
Bad stats → wrong cardinality estimates → wrong plan
✅ Index Does Not Cover Required Columns
If query needs many columns not in index:
- Table access by ROWID is expensive
- FTS preferred
🔑 Interview One‑Liner
Oracle chooses FTS when reading the table sequentially is cheaper than using an index.
2️⃣ Cardinality & Selectivity (Optimizer Brain)
Cardinality
Estimated number of rows returned by a predicate
Selectivity
Fraction of rows returned
Example:
deptno = 10
If:
- Total rows = 100,000
- Dept 10 rows = 100
✅ Highly selective
✅ Index friendly
Why This Matters
All optimizer decisions depend on cardinality estimates.
Wrong estimates → bad joins → poor plan.
3️⃣ Histograms (VERY Important)
Histograms help the optimizer understand skewed data.
Without Histogram
Oracle assumes uniform distribution.
Example:
status VARCHAR2
Values:
- A = 1%
- C = 99%
Without histogram:
- Optimizer assumes ~50/50
❌ Wrong plan chosen
With Histogram
Optimizer knows:
status='A'→ few rows → indexstatus='C'→ many rows → FTS
✅ Correct plans
Types of Histograms
- Frequency
- Height‑balanced
- Hybrid (modern Oracle)
DBA Best Practice
✅ Use histograms only on skewed columns
❌ Too many histograms = instability
Interview One‑Liner
Histograms help the optimizer choose different plans for different data values.
4️⃣ Execution Plan – How to Read It Correctly
Key Rule
Oracle executes the execution plan from the BOTTOM UP
Example Plan (Conceptual)
| Id | Operation |
|----|---------------------|
| 3 | TABLE ACCESS FULL |
| 2 | HASH JOIN |
| 1 | SELECT STATEMENT |
✅ Step 3 happens first
✅ Step 1 happens last
Important Columns to Focus On
- Operation
- Rows (estimated)
- Cost
- Predicate Information
Cost vs Rows
- Cost is optimizer‑internal
- Rows matter more for correctness
5️⃣ Join Methods Chosen by Optimizer
| Join Type | When Used |
|---|---|
| Nested Loop | Small data + index |
| Hash Join | Large data sets |
| Sort Merge Join | Ordered data, limited memory |
Common DBA Insight
If optimizer chooses nested loop on large tables, statistics are probably wrong.
6️⃣ Bind Variables & Bind Peeking
Bind Peeking Issue
Oracle peeks at first bind value and creates plan.
Example:
WHERE salary = :b1
First execution:
- b1 = 100 → index chosen
Next execution:
- b1 = 100000 → index still used ❌
Modern Oracle Fixes
- Adaptive Cursor Sharing
- Multiple child cursors
DBA Takeaway
✅ Bind variables are mandatory
✅ Adaptive features handle skew
7️⃣ Optimizer Hints – Last Resort
What Hints Are
- Suggestions
- Not guaranteed
Example:
/*+ FULL(emp) */
When Hints Are Justified
✅ Legacy SQL you cannot change
✅ Known optimizer bug
✅ Emergency production fix
When Hints Are Dangerous
❌ Data volume changes
❌ Schema changes
❌ Version upgrades
Golden Rule
Fix statistics, data model, or SQL – not the optimizer.
8️⃣ SQL Plan Baselines (Production‑Grade Feature)
What Is a SQL Plan Baseline?
A mechanism to lock good execution plans and prevent plan regression.
Why DBAs Love Baselines
- Prevent sudden performance degradation
- Safe upgrades
- Controlled plan evolution
How It Works (Conceptual)
- Optimizer finds a good plan
- DBA accepts it as baseline
- Future executions must use it
- Better plans are tested, then accepted
✅ Stability without hints
Interview One‑Liner
SQL Plan Baselines ensure plan stability while still allowing evolution.
9️⃣ Adaptive Optimizer (Modern Oracle)
Oracle can:
- Change join methods mid‑execution
- Fix wrong row estimates
- Learn during execution
✅ Good for dynamic workloads
❌ Can confuse DBAs if misunderstood
🔟 Most Common Optimizer‑Related DBA Problems
| Symptom | Root Cause |
|---|---|
| Sudden slow query | Stats refreshed |
| Index not used | Poor selectivity |
| Wrong join method | Bad cardinality |
| Plan changed after upgrade | Optimizer features |
| Inconsistent performance | Bind peeking |
✅ Perfect Interview Answers (Memorize)
- Optimizer decides HOW SQL is executed
- CBO uses statistics, not rules
- FTS is often faster than indexes
- Histograms fix skewed data estimation
- Bad plans usually mean bad statistics
- Baselines prevent plan regression
Final One‑Line Summary ⭐
The Oracle Optimizer is an intelligent engine that evaluates multiple execution plans using statistics and system resources and selects the most efficient plan to execute a SQL statement, adapting dynamically when needed.
✅ Part‑1: Reading an Oracle Execution Plan (Step‑by‑Step)
Example SQL
Example Execution Plan
🔑 GOLDEN RULE (Never Forget)
Oracle executes the execution plan from bottom to top, not top to bottom
Step‑by‑Step Execution Flow
🔹 Step 3 – TABLE ACCESS FULL DEPT
- Oracle reads entire DEPT table
- DEPT is very small (4 rows)
- Full table scan is cheapest
✅ Correct optimizer choice
🔹 Step 2 – TABLE ACCESS FULL EMP
- EMP is scanned fully
- Filter applied:
❓ Why no index?
- Likely many employees earn > 5000
- Index would return too many ROWIDs
- Full scan = sequential I/O ✅
✅ Optimizer made a cost‑based decision
🔹 Step 1 – HASH JOIN
- DEPT loaded into memory as hash table
- EMP rows probe hash table
- Efficient for larger datasets
🧠Hash join chosen because:
- EMP is large
- No usable index join path
- Sufficient memory available
🔹 Step 0 – SELECT STATEMENT
Final result returned to client
✅ What the Optimizer Decided (In English)
“Both tables are easier to scan fully, then join using a hash join rather than using indexes, because the result set is not small.”
✅ Part‑2: End‑to‑End SQL Tuning Methodology (DBA Way)
This is how you tune SQL in production, not theory.
✅ STEP‑1: Verify the Problem (Never Guess)
✅ Is the SQL really slow?
✅ Identify:
- Elapsed time
- Executions
- Buffer gets
- Disk reads
✅ STEP‑2: Examine the Execution Plan
Ask:
- Is the join method reasonable?
- Are cardinality estimates close to reality?
- Are indexes ignored?
🔴 Red flags:
- Nested loop on huge tables
- Cardinality = 1 but actual rows = 1M
- Repeated table scans
✅ STEP‑3: Check Statistics (MOST IMPORTANT)
❌ Old statistics = bad plan
✅ Refresh if needed
EXEC dbms_stats.gather_table_stats('SCOTT','EMP');
✅ STEP‑4: Check Data Distribution (Histograms)
Ask:
- Is the column skewed?
- Does optimizer assume uniform distribution?
✅ Histograms fix wrong selectivity assumptions
✅ STEP‑5: Index Evaluation (Not Creation First!)
Ask:
- Is index selective?
- Does it reduce I/O?
- Does clustering factor help?
❌ Never create an index blindly
✅ Index must justify its cost
✅ STEP‑6: SQL Rewrite (Preferred Over Hints)
Examples:
- Avoid
SELECT * - Rewrite OR conditions
- Use EXISTS instead of IN (when applicable)
✅ Better SQL → optimizer picks better plan
✅ STEP‑7: PLAN STABILITY (Production)
If SQL is business‑critical:
✅ Use SQL Plan Baselines ✅ Avoid hints unless necessary
✅ Part‑3: Common Interview Traps (with Correct Answers)
❌ Trap Question:
“Index exists, but Oracle does full table scan. Why?”
✅ Correct answer:
Because the optimizer estimated that a full table scan would cost less than using the index based on statistics and selectivity.
❌ Trap Question:
“Cost is low. Why is query still slow?”
✅ Correct answer:
Cost is an internal estimate; actual runtime depends on I/O contention, concurrency, and system load.
❌ Trap Question:
“Can optimizer choose a wrong plan?”
✅ Correct answer:
Yes, if statistics or data distribution assumptions are incorrect.
✅ Final DBA Mental Checklist
Before blaming the optimizer, always check:
✅ Statistics
✅ Cardinality
✅ Data skew
✅ Join methods
✅ Index usefulness
✅ Execution plan stability
Optimizer is usually right — until we feed it bad information.
✅ One‑Line Architect Summary ⭐
SQL tuning is about helping the optimizer make better decisions by providing accurate statistics, clear SQL, and stable execution environments—not forcing behavior with hints.
✅ Oracle Optimizer – Interview Traps & Real Fixes
(20 high‑impact questions with correct reasoning)
These are not beginner questions. They are designed to catch fake experience.
1️⃣ Oracle is using Full Table Scan even though an index exists. Why?
✅ Correct Answer: Because the optimizer estimated that a full table scan is cheaper based on:
- Selectivity
- Cardinality
- Clustering factor
- Statistics
❌ Wrong answer:
“Index is ignored”
🔑 Index existence ≠ index usage
2️⃣ Cost is low in execution plan, but query is slow. Why?
✅ Correct Answer: Cost is an estimate, not actual runtime. Slowness may be caused by:
- I/O contention
- Concurrency
- CPU pressure
- RAC GC waits
🔑 Cost ≠ time
3️⃣ Statistics are fresh, but optimizer still chooses a bad plan. Why?
✅ Possible reasons:
- Skewed data without histograms
- Bind variable peeking issues
- Adaptive features disabled
- Wrong system statistics
🔑 Statistics are necessary but not sufficient
4️⃣ Should you always gather statistics daily?
❌ NO
✅ Correct approach:
- Static tables → less frequent
- Volatile tables → more frequent
- After major data load
🔑 Blind stats gathering causes plan instability
5️⃣ Index has high cardinality. Will Oracle definitely use it?
❌ NO
✅ Optimizer also considers:
- Clustering factor
- Number of consistent gets
- Index + table access cost
6️⃣ What is the first thing to check when SQL suddenly becomes slow?
✅ Execution plan change
Then:
- Statistics refresh
- Data growth
- Environment change
❌ Not CPU or memory first
7️⃣ Does rewriting SQL help optimizer more than hints?
✅ YES
✅ Optimizer understands:
- Clear predicates
- Reduced result sets
- Better join order
❌ Hints hard‑code behavior
8️⃣ Can Oracle change execution plan during runtime?
✅ YES
Via:
- Adaptive joins
- Adaptive plans
🔑 Oracle can self‑correct within execution
9️⃣ What causes nested loops on large tables?
✅ Usually:
- Wrong cardinality
- Missing or stale statistics
🔑 Nested loop + large table = red flag
🔟 What broke after a database upgrade but SQL didn’t change?
✅ Optimizer behavior
Because:
- New optimizer features
- Different cost models
- Changed defaults
✅ Fix:
- SQL Plan Baselines
- Optimizer feature compatibility
1️⃣1️⃣ What is Clustering Factor?
✅ Measure of:
How ordered table data is relative to index order
Low CF → good index usage
High CF → many random I/Os
1️⃣2️⃣ Will adding an index always speed up SELECT?
❌ NO
✅ It increases:
- DML cost
- Redo
- Index maintenance
Indexes are trade‑offs, not free performance.
1️⃣3️⃣ What is Bind Variable Peeking?
✅ When optimizer uses the first bind value to create a plan
Fixes:
- Adaptive Cursor Sharing
- Histograms
- SQL profiles
1️⃣4️⃣ Why does optimizer prefer HASH JOIN?
✅ When:
- Large data sets
- Sufficient memory
- No suitable indexes
HASH JOIN ≠ bad join
Wrong join for workload = problem
1️⃣5️⃣ What is the most dangerous hint?
✅ FULL or INDEX hints
Why:
- Freeze execution strategy
- Break with data growth
- Cause maintenance nightmares
1️⃣6️⃣ When should SQL Plan Baselines be used?
✅ For:
- Business‑critical SQL
- Performance stability
- Upgrade protection
🔑 Baselines > hints
1️⃣7️⃣ Can optimizer choose different plans for same SQL?
✅ YES
Reasons:
- Bind values
- Adaptive cursor sharing
- Data distribution changes
1️⃣8️⃣ Why is COUNT(*) sometimes fast without index?
✅ Because Oracle:
- Can use metadata
- Can use fast full index scan
- Avoids row access
1️⃣9️⃣ What is Cardinality Misestimate?
✅ When optimizer predicts:
- Rows = 10
- Actual rows = 10,000
🔴 Root cause of bad plans
Fix = stats + histograms
2️⃣0️⃣ Who is responsible for performance: DBA or Optimizer?
✅ Shared responsibility
- Optimizer → decision engine
- DBA → gives correct inputs
🔑 Bad inputs → bad plans
✅ Real‑World Fix Scenario (Bad → Good Plan)
Problem
NEW= 90% rows- Index exists
Optimizer chooses FTS ✅
Index would be terrible ❌
👉 Correct behavior, not a bug
✅ Final Optimizer Golden Rules (Memorize)
🔥 Optimizer prefers cheapest path, not indexes
🔥 Full table scan is not evil
🔥 Bad plans usually mean bad stats
🔥 Hints hide problems, SQL fixes them
🔥 Baselines protect performance
🔥 Optimizer evolves, your SQL must too
✅ Oracle Statistics Gathering Strategy
(Deep‑Dive | Production‑Grade | Interview‑Ready)
The Oracle Optimizer is only as good as the statistics you give it.
Most optimizer problems are not optimizer bugs, but statistics problems.
1️⃣ What Are Optimizer Statistics?
Optimizer statistics describe data characteristics so Oracle can estimate cost correctly.
They answer questions like:
- How big is the table?
- How many rows match a condition?
- How selective is an index?
- Is data evenly distributed?
Types of Statistics
| Statistic Type | Purpose |
|---|---|
| Table statistics | Number of rows, blocks |
| Column statistics | Data distribution |
| Index statistics | Selectivity, clustering factor |
| System statistics | I/O and CPU cost |
| Histograms | Handle skewed data |
2️⃣ Why Statistics Are Critical (DBA View)
Without accurate stats:
- Cardinality estimates are wrong
- Join order becomes wrong
- Join method becomes wrong
- Indexes are ignored or misused
🔑 90% of bad execution plans are caused by bad or missing statistics
3️⃣ DBMS_STATS – The Only Supported Way
Oracle provides DBMS_STATS as the only supported statistics method.
❌ ANALYZE TABLE → deprecated
✅ DBMS_STATS → optimizer‑aware, safe
Basic Example
4️⃣ When Should You Gather Statistics?
✅ Gather Statistics When:
- Large data load (INSERT / UPDATE / DELETE)
- ETL or batch processing completes
- New indexes created
- Significant data growth or purge
- Performance suddenly degrades
❌ Do NOT Gather Stats Blindly:
- Daily on stable OLTP tables
- During peak business hours
- Without plan protection
Uncontrolled statistics gathering causes plan regression
5️⃣ Table Statistics Strategy
Large Transaction Tables
✅ Gather statistics incrementally ✅ Use partition‑level stats
Example:
INCREMENTAL => TRUE
Static / Master Tables
❌ Do not gather frequently
✅ Quarterly or on change only
6️⃣ Column Statistics & Histograms (Critical Topic)
When Are Histograms Needed?
Only when:
- Data is skewed
- Column appears in WHERE clause
- Column affects index choice
✅ Example:
Without histogram:
- Optimizer assumes uniform distribution
- Wrong plan chosen
Histogram Types
- Frequency
- Height‑balanced
- Hybrid (modern Oracle)
✅ Oracle chooses automatically when:
METHOD_OPT => 'FOR ALL COLUMNS SIZE AUTO'
DBA Rule
❌ Too many histograms = unstable plans
✅ Only on important skewed columns
7️⃣ Index Statistics (Often Ignored)
Optimizer uses:
- Number of leaf blocks
- Distinct keys
- Clustering factor
👉 Clustering factor matters more than index existence
A bad clustering factor:
- Causes many random I/Os
- Makes index scan expensive
- FTS becomes cheaper
8️⃣ System Statistics (Advanced but Important)
System stats tell Oracle:
- Disk I/O speed
- CPU speed
✅ Helps optimizer decide:
- Index vs full table scan
- Hash join vs nested loop
Gather using:
EXEC DBMS_STATS.GATHER_SYSTEM_STATS('NOWORKLOAD');
✅ Usually done once, not daily
9️⃣ Incremental Statistics (Data Warehouse Must‑Know)
For partitioned tables:
- Stats collected only on changed partitions
- Global stats derived automatically
Benefits: ✅ Faster
✅ Less disruption
✅ More stable plans
🔟 Statistics & Execution Plan Stability
Common Production Issue
“Query was fast yesterday, slow today.”
Root cause: ✅ Auto stats job refreshed statistics
✅ Optimizer chose a new plan
DBA Solution
✅ SQL Plan Baselines
✅ Lock known good plans
✅ Allow controlled evolution
1️⃣1️⃣ Auto Statistics Job – Friend or Enemy?
✅ Friend when:
- Well‑configured
- Stable workload
❌ Enemy when:
- Runs blindly on volatile tables
- No plan protection
✅ DBA responsibility:
- Exclude sensitive tables
- Schedule properly
1️⃣2️⃣ Statistics Gathering Best Practices (Checklist)
✅ Gather stats after large data change
✅ Use incremental stats for partitions
✅ Allow AUTO method_opt
✅ Limit histograms to skewed columns
✅ Protect critical SQL with baselines
✅ Avoid peak‑hour statistics collection
1️⃣3️⃣ Interview‑Grade Questions & Answers
Q: What is the primary input for Oracle Optimizer?
✅ Statistics
Q: Why can fresh statistics cause performance issues?
✅ Because optimizer may pick a different execution plan
Q: Should we gather statistics daily?
❌ No — only when data changes significantly
Q: How do histograms help optimizer?
✅ They handle data skew and improve selectivity estimates
🔥 One‑Line Optimizer + Statistics Formula
Good statistics + good SQL = good execution plan
✅ Architect‑Level Summary ⭐
Statistics inform the Oracle Optimizer about data size and distribution. Correct, well‑timed statistics allow the optimizer to make accurate cost‑based decisions, while poor statistics lead to bad plans, even for well‑written SQL.
1) Real Production SQL Tuning Cases (Step-by-Step)
Case A: “Sudden slowdown” after nightly jobs
Symptom: A core query’s runtime jumped from 200 ms to 5 s.
Root Cause: Auto stats job gathered fresh stats; optimizer changed join order and switched from Hash Join to Nested Loop.
Diagnosis steps:
Fix options:
- Re-gather stats with proper histograms on skewed columns.
- Create or adjust SQL Plan Baseline to pin the known good plan.
- If necessary, temporarily apply a hint (only as a stopgap).
Lesson: Stats changes → plan changes → performance changes. Stabilize with baselines and targeted histograms.
Case B: “Index exists but ignored”
Symptom: Query uses Full Table Scan despite an index on status.
Root Cause: Column is not selective (status='ACTIVE' covers 90% rows). Clustering factor is high (rows scattered), making index access expensive.
Diagnosis:
Fix options:
- Accept FTS (it’s correct).
- If a narrow subset is needed frequently, consider composite index (e.g.,
status, created_at). - Partition large tables (e.g., by date) to make scans cheaper.
Lesson: Index existence ≠ index usage. Selectivity + CF drive the decision.
Case C: “Bind peeking issue”
Symptom: Query fast for small value, slow for large value; same SQL with binds.
Root Cause: Optimizer peeks first bind, caches plan; subsequent executions reuse suboptimal plan.
Diagnosis:
Fix options:
- Enable Adaptive Cursor Sharing (usually default in modern versions).
- Use histograms on skewed columns.
- Consider SQL Plan Baselines for stability.
Lesson: Bind variability + skew → require ACS and/or histograms.
Case D: “Massive sort spill”
Symptom: Query shows TEMP usage spike, slow due to disk spills.
Root Cause: Hash join or order-by exceeds workarea memory (PGA), spilling to TEMP.
Diagnosis:
Fix options:
- Increase pga_aggregate_target or enable auto workarea tuning.
- Rewrite query to reduce sort set size (push predicates).
- Add appropriate indexes to avoid large sorts.
Lesson: Memory sizing + access path → TEMP usage → latency.
2) Oracle vs PostgreSQL Optimizer (Planner) — Key Differences
| Area | Oracle Optimizer (CBO) | PostgreSQL Planner |
|---|---|---|
| Statistics | Sophisticated (tables, columns, histograms, system stats) | Per-table/column stats, histograms via MCV/ndistinct |
| Adaptive features | Adaptive plans/joins, ACS | Limited runtime adaptation; replans happen across executions |
| Plan stability | SQL Plan Baselines, Profiles | Plan stability via enable_* knobs, constraint-based rewriting; fewer native baselining features |
| Parallel query | Mature PQ with granules and skew handling | Parallel query exists; different executor model |
| Hints | Supported (but risky) | No official hints; use config/enable/disable mechanisms |
| RAC awareness | Cache Fusion, GC waits, service affinity influence | Clustering via Patroni/PGPool doesn’t do shared-disk cache fusion; planner is node-local |
| Execution plan reading | Bottom-up operations; rich plan metadata | Explain/Analyze with buffers, JIT info; linear scans/join cost estimates |
Bottom line: Oracle’s optimizer is more feature-rich for large, mixed workloads and cluster-aware (RAC), while PostgreSQL’s planner is leaner, great for OLTP and analytics with proper indexing and config, but lacks Oracle’s adaptive and baselining capabilities.
3) Teaching Optimizer Concepts to Juniors (Mentor Script)
Level 1 (Foundation)
- Analogy: Optimizer = GPS. SQL = destination. It decides route (plan).
- Key rules:
- Optimizer uses statistics to decide.
- Full table scan isn’t evil; often cheaper.
- Sessions are logical, processes are physical (for context).
- Hands-on: Run a small query; show
EXPLAIN PLANandDBMS_XPLAN.DISPLAY.
Level 2 (Applied)
- Show how cardinality affects plan choice.
- Demonstrate histograms for skewed data.
- Compare index range scan vs full table scan with live numbers.
Level 3 (Production)
- Teach plan stability → SQL Plan Baselines.
- Show bind peeking and Adaptive Cursor Sharing examples.
- Run a case study: stats refresh → plan regression → baseline fix.
Tip: Always tie theory to an observed runtime metric (elapsed time, buffer gets, temp usage).
4) RAC-Specific Optimizer Behavior
- Service affinity matters: Place OLTP on instance A, Reporting on instance B to reduce Cache Fusion block shipping.
- Global cache impact: Queries that touch the same hot blocks across instances can see gc waits (e.g.,
gc current block busy). - Parallel query on RAC: Can distribute across instances; ensure interconnect performance and PX settings are tuned.
- Plan choice & data locality: Optimizer is not directly “RAC-aware” for cache locality, but workload placement via services indirectly improves plan outcomes by reducing cross-instance contention.
- Failover considerations: Use FAN/ONS/Application Continuity; ensure connection pools rebind properly (bind peeking nuances).
DBA rule: Optimize where the workload runs (services), not just how a query runs (plans).
5) End-to-End SQL Tuning Checklist (Print & Use)
A. Verify & Capture
- Confirm the problem (elapsed time, executions, user reports).
- Capture current execution plan (
DBMS_XPLAN.DISPLAY_CURSOR). - Record baseline metrics (buffer gets, disk reads, temp usage).
B. Data & Stats
- Check table/index stats freshness (
last_analyzed). - Validate cardinality vs actual row counts.
- Identify skewed columns → consider histograms.
- Inspect index selectivity & clustering factor.
C. Access Path & Joins
- Ensure join method suits data size (Nested Loop vs Hash Join).
- Push filters early; avoid unnecessary SELECT *.
- Consider composite/covering indexes for frequent patterns.
- Evaluate partitioning for large tables (date/range/hash).
D. Memory & Temp
- Check TEMP spills; adjust PGA/workarea if needed.
- Reduce sort/join set size via SQL rewrite.
E. Stability & Safety
- Protect critical SQL with SQL Plan Baselines.
- Avoid permanent hints unless constraints block better fixes.
- Time statistics gathering to avoid peak-hour regressions.
- In RAC, ensure proper service design (affinity).
F. Validation
- Re-test with EXPLAIN and runtime metrics.
- Compare before/after plan and performance.
- Document findings (root cause + fix + validation data).
Quick Interview One-Liners (Recap)
- “Optimizer chooses the cheapest path based on statistics; FTS can be cheaper than an index.”
- “Bad plans usually mean bad stats or wrong cardinality estimates.”
- “Use histograms for skew; protect critical SQL with baselines.”
- “In RAC, service affinity reduces cache fusion overhead.”
- “SQL tuning is about helping the optimizer, not fighting it.”
No comments:
Post a Comment