Skip to main content
MySQL Basics
CHAPTER 18 Beginner

Indexing and Query Optimization

Updated: May 16, 2026
6 min read

# CHAPTER 18

Indexing and Query Optimization

1. Introduction

When your database has 1,000 rows, every query is fast. When your database has 10 million rows, poorly written queries will bring your entire web server to a crashing halt. If you run SELECT * FROM users WHERE email = 'bob@email.com', MySQL starts at row 1 and checks every single row until it hits 10,000,000. This is a Full Table Scan, and it is the enemy of performance. In this chapter, we will learn how to create Indexes to turn 10-second queries into 10-millisecond queries.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Understand how an Index works behind the scenes.
  • Create standard and composite Indexes.
  • Identify the performance costs of over-indexing.
  • Use the EXPLAIN keyword to diagnose slow queries.
  • Optimize queries to avoid Full Table Scans.

3. What is an Index?

Think of a physical 1,000-page textbook. Your boss says: "Find the chapter on George Washington."
  • Without an Index (Full Table Scan): You flip to page 1, read it. Page 2, read it. It takes you 5 hours to find him on page 842.
  • With an Index: You flip to the Glossary at the back of the book. You jump straight to 'W' -> 'Washington'. It tells you "Page 842". You jump directly there in 5 seconds.

An Index in MySQL works exactly the same way. It is a separate, highly-organized data structure (usually a B-Tree) that keeps a sorted list of specific columns and pointers to their physical hard-drive locations.

4. Creating an Index

By default, MySQL automatically creates a powerful Index on your PRIMARY KEY column (e.g., the id). That is why searching WHERE id = 50 is instantly fast. However, we frequently search users by email. We need to manually add an index to the email column.
sql
1234
-- Syntax: CREATE INDEX index_name ON table_name (column_name);

CREATE INDEX idx_user_email 
ON users (email);

*Now, SELECT * FROM users WHERE email = 'bob@email.com' will execute in milliseconds, even with 10 million users!*

5. Composite Indexes

If your application constantly searches using two columns at the same time (e.g., WHERE lastname = 'Smith' AND firstname = 'John'), you can create a single index that covers both!
sql
12
CREATE INDEX idx_last_first_name 
ON users (last_name, first_name);

6. The EXPLAIN Keyword (The Detective Tool)

How do you know if MySQL is actually using your Index, or if it is secretly doing a Full Table Scan? You put the word EXPLAIN in front of your query!
sql
1
EXPLAIN SELECT * FROM users WHERE email = 'bob@email.com';

MySQL will not run the query. Instead, it will output a diagnostic table. Look at the type and rows columns in the output:

  • type: ALL -> Catastrophe. This means a Full Table Scan. It checked every row.
  • type: ref or const -> Success! It used an index.
  • rows: 1 -> Incredible! It found the data by examining exactly 1 row instead of 10 million.

7. The Dark Side of Indexing (Write Penalties)

If Indexes make reading data lightning fast, why don't we just put an Index on every single column in the table? Because Indexes slow down INSERT, UPDATE, and DELETE queries. If you have 15 indexes on a table, every time a new user registers (INSERT), MySQL has to physically write the user to the hard drive, and then pause to update 15 separate B-Tree index files before it can finish. This will cripple write-heavy applications. *Rule of Thumb:* Only index columns that are heavily used in WHERE, ORDER BY, or JOIN clauses.

8. Avoiding Full Table Scans

Even if you have an index, writing bad SQL can force MySQL to ignore it!
  1. 1. Leading Wildcards: WHERE email LIKE '%@gmail.com' completely breaks the index. MySQL must check every row.
  1. 2. Math on the Column: WHERE YEAR(createdat) = 2024 breaks the index on createdat. MySQL has to extract the year from every single row before comparing. Instead, write it as a range: WHERE createdat BETWEEN '2024-01-01' AND '2024-12-31'.

9. Common Mistakes

  • Indexing Low Cardinality Columns: "Cardinality" means uniqueness. A column like email has high cardinality (every row is different) -> Great for an Index. A column like isactive has low cardinality (only 1s and 0s). An index on isactive is virtually useless and wastes space, as MySQL will likely just table-scan anyway.

10. Best Practices

  • Monitor Slow Queries: In production, enable the "MySQL Slow Query Log". It automatically records any query that takes longer than 2 seconds to execute. You can review this log weekly, find the slow queries, run EXPLAIN on them, and add the missing Indexes!

11. Exercises

  1. 1. Write the SQL command to create an index named idxdepartment on the department column of the employees table.
  1. 2. If you execute an EXPLAIN query and the type column returns ALL, what is MySQL doing?

12. MCQ Quiz with Answers

Question 1

Why shouldn't a database developer place an Index on every single column in a table?

Question 2

Which keyword can you prepend to a SELECT statement to view the execution plan and verify if MySQL is utilizing your Indexes?

13. Interview Questions

  • Q: Explain what a "Full Table Scan" is, why it degrades performance on large datasets, and how implementing an Index resolves it.
  • Q: A developer has an index on the createddate column. They write a query: WHERE MONTH(createddate) = 12. The query is incredibly slow. Explain why the index failed and how to rewrite the query.

14. FAQs

Q: Do Foreign Keys automatically get an Index? A: In MySQL (specifically the InnoDB engine), yes! When you create a FOREIGN KEY constraint, MySQL automatically creates a hidden Index on that column to ensure JOIN queries remain fast.

15. Summary

Indexing is the difference between an amateur database and an enterprise architecture. By intelligently placing Indexes on frequently searched columns, avoiding index-breaking syntax like leading wildcards, and utilizing the EXPLAIN command to diagnose bottlenecks, you guarantee your application remains responsive at massive scale.

16. Next Chapter Recommendation

We have optimized our data retrieval. But how do we enforce data quality upon insertion? If an E-commerce product must never have a negative price, how do we block it at the database level? In Chapter 19: Constraints and Data Integrity, we will implement iron-clad data validation rules.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·