Back to Blog
Lesson 30 of the Database Design: Data Modeling & Normalization Basics course
DatabasesAugust 18, 20264 min read

Auditing Schema Performance: How to Read SQL EXPLAIN Plans

Learn how to use EXPLAIN plans to audit your schema performance. Discover how to identify slow queries in your SaaS project and optimize them for production.

SQLDatabase PerformanceOptimizationEXPLAINSaaS
Overhead view of an office desk with financial documents, a magnifying glass, and stationery items, suggesting business analysis.

Previously in this course, we explored Designing Composite Indexes: A Guide to SQL Performance and discussed the overhead of indexes. While indexes are a powerful tool, you can't optimize what you haven't measured. This lesson moves from theory to practice, teaching you how to use the EXPLAIN command to see exactly how your database engine executes your SQL queries.

Why Every Developer Needs to Audit Schema Performance

In a production SaaS environment, "it works on my machine" is a dangerous metric. A query that runs in 10ms with 50 rows of test data might take 10 seconds with 50,000 rows. Performance auditing isn't about guessing; it's about observing the query planner's choices.

When you run a SELECT statement, the database doesn't just "find the data." It builds a tree of operations—a plan—to retrieve that data in the most efficient way it knows how. The EXPLAIN command asks the database to reveal this internal map.

Decoding the EXPLAIN Plan

To audit your queries, prepend EXPLAIN (or EXPLAIN ANALYZE for actual execution statistics) to any SELECT query.

SQL
EXPLAIN ANALYZE 
SELECT * FROM subscriptions 
WHERE account_id = 42;

When you run this, you'll see a series of nodes. Here is a simple mental model of what you are looking for:

  • Sequential Scan (or Table Scan): The database is reading every single row in the table to find your match. This is the "red flag" of performance auditing. If your table has 100,000 rows, a sequential scan is incredibly slow.
  • Index Scan: The database is using a B-tree index (like we discussed in Primary Key Indexing: How Clustered Indexes Boost Performance) to jump directly to the target rows. This is usually what you want.
  • Cost/Time: Most engines provide an estimated "cost" or actual execution time. Use this to compare different versions of a query.

Worked Example: Identifying a Bottleneck

Imagine our SaaS project has a user_activity table. We want to find all logins for a specific user within a date range.

The Slow Query:

SQL
EXPLAIN ANALYZE
SELECT * FROM user_activity 
WHERE user_id = 101 
ORDER BY activity_date DESC;

The Output (Simplified):

TEXT
Sort  (cost=100.50..100.51 rows=1 width=32) (actual time=45.2ms)
  -> Seq Scan on user_activity  (cost=0.00..100.49 rows=1 width=32)
     Filter: (user_id = 101)

The Audit Findings:

  1. Seq Scan: We are scanning the entire table.
  2. Cost: It took 45.2ms to find one user's data.
  3. The Fix: We clearly lack an index on user_id. After adding CREATE INDEX idx_user_activity_user_id ON user_activity(user_id);, the plan changes to an Index Scan, likely dropping the time to <1ms.

Hands-on Exercise

  1. Pick one of the SELECT queries from your project's CRUD implementation.
  2. Run EXPLAIN ANALYZE on that query.
  3. Look for any line saying "Sequential Scan" on a table that you expect to be queried by an ID or a filter.
  4. If you find one, create an index on the column(s) used in the WHERE clause and run the EXPLAIN again to observe the difference.

Common Pitfalls

  • Ignoring "Estimated" vs. "Actual": EXPLAIN gives estimates. EXPLAIN ANALYZE actually runs the query and gives you real timing data. Always use ANALYZE when debugging performance, but be careful with UPDATE or DELETE queries—wrap them in a transaction (BEGIN; ... ROLLBACK;) if you don't want to change your data.
  • Over-Indexing: Just because a query is slow doesn't mean you should add an index for every column. Indexes slow down INSERT and UPDATE operations. Always verify if the query truly needs that index.
  • Misinterpreting "Cost": Database costs are arbitrary units. Don't worry about the specific number, worry about the change in the number when you add an index or rewrite a query.

Frequently Asked Questions

Q: Does EXPLAIN slow down my database? A: EXPLAIN (without ANALYZE) is instantaneous. EXPLAIN ANALYZE executes the query, so it takes as long as the query itself.

Q: My query is still slow even with an index. What now? A: You might be selecting too many columns (SELECT *). Try selecting only the columns you need. Alternatively, your index might not be "covering" the query, or your data statistics might be stale.

Q: Is a Sequential Scan ever okay? A: Yes. If the table is very small (e.g., a "settings" table with 5 rows), the database engine will intentionally perform a sequential scan because it's faster than traversing an index.

Recap

Performance auditing is the act of looking at the database's execution plan to verify that it is using your indexes as intended. By reading EXPLAIN plans, you can catch "Sequential Scans" before they become production outages.

Up next: We will look at how to manage Handling Large Data Sets to ensure your SaaS schema remains performant even as your user base grows.

Similar Posts