📡 You're offline — showing cached content
New version available!
Quick Access
SQL Advanced

MySQL Performance Tuning: EXPLAIN ANALYZE and Slow Query Log

Fix slow MySQL queries — enable slow query log, read every EXPLAIN field, identify full table scans, filesorts, and apply targeted fixes.

EzyCoders Admin November 9, 2025 12 min read 0 views
MySQL Performance Tuning EXPLAIN Guide
Share: Twitter LinkedIn WhatsApp

MySQL Performance Tuning

A slow MySQL query can bring down an entire application. Learning to read EXPLAIN output, use the slow query log, and apply targeted fixes is one of the most valuable skills a backend developer can have.

-- Enable slow query log
SET GLOBAL slow_query_log     = 'ON';
SET GLOBAL long_query_time    = 1;      -- queries over 1 second
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';

-- Find top slow queries
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
-- -s t: sort by total time  -t 10: top 10

Reading EXPLAIN Output

EXPLAIN SELECT u.name, COUNT(p.id) AS posts
FROM users u
LEFT JOIN posts p ON p.user_id = u.id
WHERE u.active = 1
GROUP BY u.id;

-- id | select_type | table | type  | key           | rows | Extra
-- ---|-------------|-------|-------|---------------|------|------------------
--  1 | SIMPLE      | u     | ref   | idx_active    |  100 | Using index
--  1 | SIMPLE      | p     | ref   | idx_user_id   |    5 | Using index

-- type values (best to worst):
-- system: single row table
-- const:  single row match (primary/unique key)
-- eq_ref: one row per join (primary key join)
-- ref:    index lookup, multiple rows possible ← GOOD
-- range:  index range scan (BETWEEN, >, <)    ← OK
-- index:  full index scan                      ← WARN
-- ALL:    full table scan                      ← BAD, add index!

-- EXPLAIN ANALYZE (MySQL 8.0.18+): shows actual execution
EXPLAIN ANALYZE SELECT * FROM posts WHERE category_id = 3;

Fixing Common Performance Issues

-- Problem 1: Full table scan on large table
SELECT * FROM orders WHERE status = 'pending';
-- Fix: add index
ALTER TABLE orders ADD INDEX idx_status (status);

-- Problem 2: N+1 via ORM — detect with query count
-- Fix: use JOINs or eager loading

-- Problem 3: SELECT * fetching unnecessary columns
SELECT * FROM posts;
-- Fix: only select what you need
SELECT id, title, published_at FROM posts;

-- Problem 4: Filesort (ORDER BY not using index)
EXPLAIN SELECT * FROM posts ORDER BY views DESC;
-- key=NULL + Extra='Using filesort' = bad
-- Fix: add index on views
ALTER TABLE posts ADD INDEX idx_views (views);

-- Problem 5: Temporary table in GROUP BY
-- Fix: ensure GROUP BY column is indexed

-- Covering index (serves query entirely from index — fastest)
ALTER TABLE posts ADD INDEX idx_cover (status, user_id, title, published_at);
SELECT title, published_at FROM posts WHERE status='published' AND user_id=42;
-- Extra: 'Using index' (no table access needed!)

Q: What does Extra: Using filesort mean in EXPLAIN?

MySQL cannot use an index to satisfy the ORDER BY — it must sort the result in memory or on disk after fetching rows. This is expensive for large datasets. Fix by adding an index that matches the ORDER BY columns, ensuring the index column order matches, and that the WHERE clause doesn't conflict with the sort index.

EzyCoders Admin
Written by
EzyCoders Admin

Team Lead and Full-Stack Developer with experience in PHP, JavaScript, SQL, DSA, and System Design. Passionate about software engineering, scalable web technologies, and helping developers prepare for coding interviews and tech careers through practical tutorials and professional guidance.

Comments (0)

No comments yet. Be the first!

Leave a Comment