DevLearningTools

LEARN · SQL

SQL EXPLAIN and Execution Plans

An execution plan shows exactly how the database intends to run a query, scan or seek, which index if any, in what order. Learn to read one, and the real EXPLAIN syntax split across all six databases, since none of them share a single standard statement for it.

The last lesson said an index makes a lookup faster, an execution plan is how to actually confirm whether a given query is using one at all, instead of assuming it is.

Learning Objectives

  • Explain what an execution plan is, and get one for a given query on a specific database.
  • Read a plan well enough to tell an index-based access apart from a full table scan.
  • Know the real EXPLAIN syntax split across all six databases, since none of them share one standard statement for it.

Ask for a Plan

EXPLAIN, or its database-specific equivalent

Plan Chosen

Scan or seek, join order, cost estimate

Read It

Spot a scan that should have been a seek

What an Execution Plan Shows

Before running a query, the database's optimizer picks an access method for each table involved (a full scan, or a specific index), a join algorithm and order if more than one table is involved, and a relative cost estimate for each step based on table statistics. An execution plan is that chosen plan, made visible, in most cases without even running the query for real.

The Real EXPLAIN Syntax, by Database

DatabaseHow to Get an Execution Plan
MySQL / MariaDBEXPLAIN SELECT ...; MySQL (8.0.18+) also has EXPLAIN ANALYZE SELECT ...;, MariaDB's own form (10.1+) is the separate statement ANALYZE SELECT ...;, not EXPLAIN ANALYZE.
PostgreSQLEXPLAIN SELECT ...; (plan only, doesn't run the query) or EXPLAIN ANALYZE SELECT ...; (actually executes it, and reports real timings).
SQLiteEXPLAIN QUERY PLAN SELECT ...; Plain EXPLAIN alone dumps internal VDBE bytecode, not a human-readable plan, EXPLAIN QUERY PLAN is the one worth using.
SQL ServerNo EXPLAIN keyword exists at all. SET SHOWPLAN_ALL ON; (plan only) or SET STATISTICS PROFILE ON; (plan plus real run stats) before running the query, or SSMS's graphical "Display Estimated/Actual Execution Plan" buttons.
OracleA two-statement process: EXPLAIN PLAN FOR SELECT ...; followed by SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

Getting a Plan for the Same Query

MySQL / MariaDB
EXPLAIN
SELECT * FROM employees WHERE department_id = 3;
PostgreSQL
EXPLAIN
SELECT * FROM employees WHERE department_id = 3;
SQLite
EXPLAIN QUERY PLAN
SELECT * FROM employees WHERE department_id = 3;
SQL Server
SET SHOWPLAN_ALL ON;
SELECT * FROM employees WHERE department_id = 3;
Oracle
EXPLAIN PLAN FOR
SELECT * FROM employees WHERE department_id = 3;

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

Reading a Plan: Scan vs Index, by Database

Every database's plan answers the same question, full scan or index access, but each one names that answer differently.

DatabaseFull ScanUsing an Index
MySQL / MariaDBtype: ALLtype: const / eq_ref / ref / range / index
PostgreSQLSeq ScanIndex Scan / Index Only Scan / Bitmap Index Scan
SQLiteSCAN TABLESEARCH TABLE ... USING INDEX
SQL ServerTable Scan / Clustered Index ScanIndex Seek / Clustered Index Seek
OracleTABLE ACCESS FULLINDEX RANGE SCAN / INDEX UNIQUE SCAN

Try It Yourself

Get an execution plan for a query filtering employees by last_name on MySQL, and decide whether an index on last_name would change the plan's access type.

Answer
EXPLAIN
SELECT * FROM employees WHERE last_name = 'Nguyen';
-- type: ALL means a full scan, department_id has an index from an
-- earlier lesson, last_name doesn't yet, so this is expected to read ALL.

Frequently Asked Questions

Does running EXPLAIN affect the real data, or lock the table?

No, for a plain EXPLAIN on any of these six databases, it only asks the optimizer for its plan without executing the query. The exceptions are the ANALYZE variants (PostgreSQL's EXPLAIN ANALYZE, MySQL's EXPLAIN ANALYZE, MariaDB's ANALYZE, SQL Server's STATISTICS PROFILE), which run the query for real to report actual timings, exactly as the query would otherwise run, including any writes an UPDATE or DELETE would make.

Does a plan guarantee the fastest way to run the query?

No, it reflects the optimizer's best cost estimate from the table's statistics, which can be out of date or simply wrong, actual performance can differ from the estimate. That's exactly why the ANALYZE-style variants exist, to compare the estimated cost against what actually happened.

Common Beginner Mistakes

Running EXPLAIN ANALYZE on an UPDATE or DELETE during testing, expecting it not to run for real

On PostgreSQL and MySQL, EXPLAIN ANALYZE genuinely executes the statement, including its write effects, it isn't a dry run. Wrap it in a transaction and roll back afterward when testing a destructive statement this way.

Expecting a plain EXPLAIN on SQLite to produce a readable plan

Plain EXPLAIN on SQLite dumps internal VDBE bytecode, not a human-readable access plan. EXPLAIN QUERY PLAN is the statement that actually shows SCAN TABLE vs SEARCH TABLE ... USING INDEX.

Best Practices

  • Check the actual plan before assuming an index is being used, don't just assume it.
  • On PostgreSQL and MySQL, run a destructive statement's EXPLAIN ANALYZE inside a transaction you roll back, since it genuinely executes.
  • Compare plans before and after adding or removing an index on the real table size, an optimizer can skip an index entirely on a tiny test table since a full scan is already cheap there.

Interview Questions

What's the difference between EXPLAIN and EXPLAIN ANALYZE on PostgreSQL?

EXPLAIN alone only asks the optimizer for its chosen plan and estimated costs, without running the query. EXPLAIN ANALYZE actually executes the query, and reports real elapsed time and row counts for each step alongside the original estimates, letting you compare what the optimizer expected against what actually happened.

Why does SQL Server have no EXPLAIN statement, and what's the real equivalent there?

SQL Server simply never implemented EXPLAIN as a keyword, its own plan-inspection tools are SET SHOWPLAN_ALL ON; or SET STATISTICS PROFILE ON; run before the query, or SQL Server Management Studio's graphical "Display Estimated/Actual Execution Plan" buttons, which show the same kind of plan through a different interface entirely.

Summary

An execution plan shows exactly how a query is actually going to run, or did run, scan type, index usage, join order, and cost. Getting one is genuinely different SQL on every one of these six databases, from a single EXPLAIN keyword to SQL Server's complete absence of one, and each database names "full scan" and "using an index" with its own distinct plan terminology.

What's Next?

The last lesson in this module ties indexes and execution plans together into practical habits: which columns are actually worth indexing, and the query patterns that quietly defeat an index that already exists.

</>

Ready to Practice SQL?

Write and run real SQL queries online, right in your browser, no install or signup required. Pick a playground based on which database you want to practice on.

SQLite / PostgreSQL

Fast, no server, no ads.

Open DB Fiddle ↗

MySQL / SQL Server

Switch databases with one dropdown.

Open SQL Fiddle ↗

Both open a third-party SQL playground in a new tab. External site terms and privacy policy apply.

Or try 50 SQL practice questions →