SQL EXPLAIN


SQL
POSTGRES
INTERACTIVE

Complete SQL EXPLAIN Technical Guide

1. Fundamental Syntax
-- Standard EXPLAIN syntax
EXPLAIN [ANALYZE] [VERBOSE] query;

-- MySQL variant
EXPLAIN [FORMAT = {JSON | TREE | TRADITIONAL}] query;

-- PostgreSQL variant
EXPLAIN [ANALYZE] [BUFFERS] [FORMAT {TEXT | XML | JSON | YAML}] query;
  1. ANALYZE: Actually executes the query and shows real runtime statistics
  2. VERBOSE: Displays additional details about the plan
  3. FORMAT: Changes output format (JSON, XML, etc.)
  4. Database Variations: Significant differences exist between MySQL, PostgreSQL, SQL Server, and Oracle
2. Interpreting EXPLAIN Output
Key Plan Operations
/* PostgreSQL example */
EXPLAIN ANALYZE SELECT * FROM orders WHERE customer_id = 123;

QUERY PLAN
------------------------------------------------------------------
Index Scan using idx_orders_customer on orders  (cost=0.29..8.31 rows=1 width=45)
  Index Cond: (customer_id = 123)
  Planning Time: 0.114 ms
  Execution Time: 0.028 ms
Cost Metrics Explained
/* MySQL example */
EXPLAIN FORMAT=JSON SELECT * FROM products WHERE price > 100;

{
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": "325.65"
    },
    "table": {
      "access_type": "range",
      "rows_examined_per_scan": 500,
      "rows_produced_per_join": 500,
      "filtered": "100.00",
      "cost_info": {
        "read_cost": "300.25",
        "eval_cost": "25.40",
        "prefix_cost": "325.65"
      }
    }
  }
}
3. Optimization Using EXPLAIN
Identifying Performance Issues
-- PostgreSQL example showing a problematic sequential scan
EXPLAIN ANALYZE SELECT * FROM large_table WHERE last_name LIKE 'Smith%';

QUERY PLAN
------------------------------------------------------------------
Seq Scan on large_table  (cost=0.00..12548.20 rows=1000 width=45)
  Filter: (last_name ~~ 'Smith%'::text)
  Rows Removed by Filter: 999000
  Planning Time: 0.112 ms
  Execution Time: 1250.456 ms
After Adding an Index
-- After creating index: CREATE INDEX idx_last_name ON large_table(last_name)
EXPLAIN ANALYZE SELECT * FROM large_table WHERE last_name LIKE 'Smith%';

QUERY PLAN
------------------------------------------------------------------
Bitmap Heap Scan on large_table  (cost=24.33..826.45 rows=1000 width=45)
  Filter: (last_name ~~ 'Smith%'::text)
  -> Bitmap Index Scan on idx_last_name  (cost=0.00..24.08 rows=1000)
       Index Cond: (last_name ~~ 'Smith%'::text)
  Planning Time: 0.456 ms
  Execution Time: 2.123 ms
4. Database-Specific EXPLAIN Features
SQL Server Execution Plans
-- SQL Server graphical execution plan
SET SHOWPLAN_XML ON;
GO
SELECT p.Name, c.Name 
FROM Products p
JOIN Categories c ON p.CategoryID = c.CategoryID;
GO
SET SHOWPLAN_XML OFF;

-- Estimated vs Actual execution plans
-- Use "Include Actual Execution Plan" in SSMS or:
SET STATISTICS PROFILE ON;
Oracle Explain Plan
-- Oracle EXPLAIN PLAN
EXPLAIN PLAN FOR
SELECT e.last_name, d.department_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id;

-- View the plan
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

-- Advanced options
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(
    format => 'ALLSTATS LAST +OUTLINE +NOTE'
));
5. Advanced EXPLAIN Analysis
Analyzing Join Strategies
-- PostgreSQL example showing different join types
EXPLAIN ANALYZE SELECT o.*, c.*
FROM orders o
JOIN customers c ON o.customer_id = c.id;

QUERY PLAN
------------------------------------------------------------------
Hash Join  (cost=129.57..312.45 rows=1000 width=145)
  Hash Cond: (o.customer_id = c.id)
  -> Seq Scan on orders o  (cost=0.00..145.00 rows=10000)
  -> Hash  (cost=98.76..98.76 rows=876 width=72)
       -> Seq Scan on customers c  (cost=0.00..98.76 rows=876)
Understanding Parallel Execution
-- PostgreSQL parallel query example
EXPLAIN ANALYZE SELECT * FROM large_table WHERE value > 1000;

QUERY PLAN
------------------------------------------------------------------
Gather  (cost=1000.00..12548.20 rows=100000 width=45)
  Workers Planned: 4
  Workers Launched: 4
  -> Parallel Seq Scan on large_table  (cost=0.00..10548.20 rows=25000)
       Filter: (value > 1000)
  Planning Time: 0.112 ms
  Execution Time: 125.456 ms
6. Performance & Best Practices
  1. Always use ANALYZE: For real-world performance metrics (but remember it executes the query)
  2. Compare plans: Before and after changes to verify improvements
  3. Look for warning signs: Sequential scans on large tables, high row estimates vs actuals, expensive sorts
  4. Understand cost units: Cost is arbitrary but consistent within a database
  5. Use visual tools: Many GUIs provide graphical explain plans that are easier to interpret
Common Optimization Patterns
-- Example of optimizing with EXPLAIN
-- Problem query:
EXPLAIN ANALYZE SELECT * FROM orders WHERE EXTRACT(YEAR FROM order_date) = 2023;

-- Optimized version:
EXPLAIN ANALYZE SELECT * FROM orders 
WHERE order_date BETWEEN '2023-01-01' AND '2023-12-31';

-- Create function-based index if needed:
CREATE INDEX idx_orders_year ON orders(EXTRACT(YEAR FROM order_date));

Advanced EXPLAIN Clause Insights

1. Execution Plan Visualizations

Modern database tools transform EXPLAIN output into interactive diagrams.

-- Tools that enhance EXPLAIN analysis:
• PostgreSQL: pgAdmin's graphical EXPLAIN
• MySQL: Workbench's Visual Execution Plan
• SQL Server: SSMS's Live Query Statistics
• Oracle: SQL Developer's Plan Visualization
  1. Node Tree Navigation: Click-through exploration of complex plans
  2. Cost Heatmaps: Color-coded highlighting of expensive operations
  3. Tooltip Details: Hover-over explanations of plan operators
2. Planner Statistics Analysis

EXPLAIN relies on database statistics that sometimes need maintenance.

-- PostgreSQL statistics commands
ANALYZE table_name;  -- Update statistics
EXPLAIN (ANALYZE, BUFFERS) SELECT... -- Show buffer usage

-- MySQL statistics refresh
ANALYZE TABLE table_name;
OPTIMIZE TABLE table_name;
  1. Cardinality Estimation: Why row estimates may be inaccurate
  2. Histogram Bounds: How data distribution affects plans
  3. Statistics Age: Checking when stats were last updated
3. Plan Regression Analysis

Tracking when and why execution plans change unexpectedly.

-- PostgreSQL plan capture
CREATE EXTENSION pg_store_plans;

-- MySQL optimizer switch control
SET optimizer_switch='block_nested_loop=off';

-- SQL Server plan forcing
EXEC sp_create_plan_guide_from_handle 'template_plan', @plan_handle;
  1. Plan Baselines: Oracle's SQL Plan Management
  2. Plan Hinting: Directing the optimizer (MySQL's FORCE INDEX)
  3. Plan Freezing: PostgreSQL's plan_cache_mode
4. Distributed Query Analysis

EXPLAIN for sharded, partitioned, and federated queries.

-- PostgreSQL partition analysis
EXPLAIN ANALYZE SELECT * FROM partitioned_table WHERE date > '2023-01-01';

-- Citus (PostgreSQL extension) distributed plan
EXPLAIN (VERBOSE) SELECT * FROM distributed_table JOIN local_table USING (id);
  1. Shard Routing: Identifying which shards are accessed
  2. Network Costs: Cross-node join penalties
  3. Partition Pruning: Verifying unneeded partitions are excluded
5. Transaction Context Effects

How transaction isolation and data visibility affect plans.

-- PostgreSQL example showing transaction impact
BEGIN;
SET LOCAL enable_indexscan = off;
EXPLAIN SELECT * FROM table_name WHERE condition;
COMMIT;

-- SQL Server snapshot isolation
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
EXPLAIN SELECT * FROM table_with_heavy_updates;
  1. Parameter Sniffing: SQL Server's plan caching behavior
  2. Temporary Table Stats: How temp tables affect plan quality
  3. Plan Invalidation: When DDL changes force recompilation
Not Included Topics
  1. Query Plan Fingerprinting: Cryptographic hashing of plans for comparison
  2. ML-Based Plan Prediction: Using machine learning to forecast plan changes
  3. Cross-Vendor Plan Translation: Converting plans between different database systems
  4. Plan Change Alerting: Monitoring systems for unexpected plan regressions
  5. EXPLAIN for NoSQL Systems: How document databases like MongoDB handle execution plans