How to Create Index in MySQL? A Complete Guide

By Rohan Vats

Updated on Jun 12, 2025 | 7 min read | 14.79K+ views

Share:

Do you know? A well-designed index can make queries up to 30x faster in MySQL, but over-indexing can slow down write operations and increase storage requirements. Striking the right balance is crucial for optimal database performance!

In MySQL, as your database grows, retrieving data becomes slower. Without an efficient way to search through the data, queries can take significantly longer to execute. Imagine you have a table with millions of records, and you need to find a specific entry based on a column like "customer_id." Without an index, MySQL would need to scan the entire table to find the match.

By creating an index on that column, MySQL can quickly locate the row, similar to how an index in a book helps you find the relevant page without flipping through every page. 

In this blog, you'll explore the different types of indexes in MySQL, how to create them, and the best practices to ensure you're optimizing your database for performance.

Want to learn how to create index in MySQL? Join upGrad’s Online Software Development Courses and work on hands-on projects that simulate real industry scenarios. With a focus on trending programming languages and the latest technologies, you’ll be equipped for coding success.

How to Create Index in SQL? A Step-By-Step Guide

Creating an index in SQL can lead to dramatic improvements in query performance, sometimes reducing query times from several seconds to milliseconds, especially on large tables. 

For example, on a table with millions of rows, a well-designed index can make data retrieval up to 100x faster compared to a full table scan. 

In real-world scenarios, adding an index on a frequently searched column (such as an email or user ID) can reduce query latency from over 2 seconds to under 50 milliseconds on a 10-million-row table.

In 2025, professionals who can create and use an index in MySQL to streamline querying will be in high demand. If you're looking to develop skills in MySQL and other coding tasks, here are some top-rated courses to help you get there:

Here’s how you can create an index in MySQL:

Step 1: Analyze Your Workload and Queries

Use tools like SQL Profiler or Query Store to identify slow queries and determine which columns are most often used in WHERE clauses, JOINs, or ORDER BY operations.

Focus on indexing columns with high cardinality (many unique values) for maximum selectivity and impact.

Step 2: Write the CREATE INDEX Statement

CREATE INDEX idx_customers_email
ON customers (email);

This command creates an index named idx_customers_email on the email column of the customers table. After creation, queries like:

SELECT * FROM customers WHERE email = 'user@example.com';

can leverage the index, resulting in much faster lookups. You can verify index usage with an EXPLAIN plan, which should show an "Index Scan" if the index is being utilized.

Output: No direct output, but query performance metrics (such as query execution time) will improve significantly for indexed columns. On a large dataset, expect query times to drop from seconds to milliseconds.

Step 3: Consider Composite Indexes for Multi-Column Searches

CREATE INDEX idx_orders_customer_date
ON orders (customer_id, order_date);

Explanation: This composite index accelerates queries filtering by both customer_id and order_date, but note that the order of columns matters—this index is most effective when queries filter on customer_id first.

Step 4: Monitor and Tune

Avoid over-indexing: Each additional index increases storage and slows down data modification (INSERT/UPDATE/DELETE) operations.

For heavily updated tables, keep indexes as narrow (few columns) as possible. Use database tools to monitor index usage and remove unused or redundant indexes.

Key Considerations:

  • Indexing a column with high cardinality can reduce scanned rows by over 99%, especially on large tables.
  • Indexes are generally not needed for small tables (a few hundred rows or less), as full scans are already fast.
  • Over-indexing can degrade write performance by 20–50% or more on high-transaction tables.
  • Naming indexes descriptively (e.g., idx_table_column) helps with future maintenance.

By strategically creating indexes based on actual query patterns and data characteristics, you can achieve substantial real-world performance gains in your SQL databases.

Strengthen your SQL skills and learn how to use functions and formulas to handle data more efficiently in Power BI. Start with upGrad's free Advanced SQL: Functions and Formulas course today and take a step toward higher-paying roles in data.

Also Read: SQL for Data Science: A Complete Guide for Beginners

Now that you know how to create Index in MySQL, let’s look at some best practices you can follow for optimal results.

How to Alter a Table to Add or Drop Index?

Altering a table to add or drop an index is a common database maintenance task aimed at optimizing query performance or managing storage and write efficiency. 

While creating an index is typically done with a CREATE INDEX statement, removing (dropping) an index can be accomplished using either the DROP INDEX statement or, in some database systems, through the ALTER TABLE statement. The specific syntax and approach can vary depending on the SQL dialect (e.g., MySQL, SQL Server, PostgreSQL).

Software Development Courses to upskill

Explore Software Development Courses for Career Progression

Coverage of AWS, Microsoft Azure and GCP services

Certification8 Months

Job-Linked Program

Bootcamp36 Weeks

To add indexes to a table, there are four types of statements that can be used:

1. To add a primary key:

ALTER TABLE table_name ADD PRIMARY KEY (column_list);

The indexed values here should be unique and cannot be NULL.

2. For an index with unique values:

ALTER TABLE table_name ADD UNIQUE index_name (column_list);

The values should be unique, except for NULL which can appear multiple times.

3. To add an ordinary index:

ALTER TABLE table_name ADD INDEX index_name (column_list);

Here the values can appear more than once.

4. To create special FULLTEXT index:

ALTER TABLE table_name ADD FULLTEXT index_name (column_list);

The FULLTEXT index can be used for text searching purposes.

Now, let’s look at how you can add index in MySQL for existing tables.

To add index in any existing table, the following syntax can be used:

ALTER TABLE table_name ADD INDEX (index_name);

To delete an index in a table, the DROP INDEX statement is used:

ALTER TABLE table_name DROP INDEX (index_name);

To list all the indexes associated with any table, the SHOW INDEX command is used.

SHOW INDEX FROM table_name\G

The ‘\G’ is used to create the list in a vertical format, this avoids the long line wraparound.

Also Read: SQL Interview Questions & Answers

How to Use Descending Indexes?

InnoDB can store the entries in descending order when the index is a descending index. So, when the descending order is requested in the query, the optimizer chooses this index. This is more efficient for queries with ORDER BY clauses. These are only supported by the InnoDB storage engine.

The syntax for creating or adding descending indexes is like alter or create syntaxes used above.

ALTER TABLE table_name ADD index_name (col1_name desc, col2_name asc);

CREATE INDEX index_name ON table_name (col1_name desc, col2_name asc);

The following occurs in MySQL (InnoDB engine, version 8.0+):

  • Physical Storage Order: The index entries for col1_name are stored in descending order, while col2_name is stored in ascending order within the index structure. This is fundamentally different from the default (ascending) storage and directly impacts how the database retrieves and sorts data.
  • Query Optimization: The optimizer can now efficiently use this index for queries that request results ordered by col1_name DESC, col2_name ASC (or the reverse, depending on the query). This means MySQL can scan the index in the order required by the query, avoiding expensive filesorts and reducing query execution time—especially beneficial on large datasets.
  • Performance Impact: For queries with ORDER BY col1_name DESC, col2_name ASC, the database engine can perform a forward scan of the index, which is much faster than scanning an ascending index in reverse order. For the opposite order (ORDER BY col1_name ASC, col2_name DESC), the engine can perform a backward scan of the same index14. This flexibility leads to significant performance gains for sorting operations.
  • Verification: You can verify index creation and usage with SHOW INDEX FROM table_name;, where the Collation column will show D for descending and A for ascending. The EXPLAIN plan for relevant queries will indicate index usage, often showing "Backward index scan" or "Using index".
  • Limitations: Descending indexes are only supported by the InnoDB storage engine. Attempting to use them with other engines or with unsupported index types (e.g., SPATIAL or HASH) will result in an error.

Are you interested in knowing how to structure, create, and manage databases using MySQL? upGrad’s free Introduction to Database Design with MySQL course covers ER models, normalization, SQL queries, and relational schema concepts.

Also Read: SQL Interview Questions & Answers from Beginner to Expert Guide

How to Create Invisible Index in MySQL?

To mark indexes as unavailable for the query optimizer, invisible indexes can be used. MySQL updates invisible indexes when the data in columns associated with the index changes. Indexes are visible by default and to make them invisible, you have to explicitly declare the visibility at the time of creation or by using the ALTER TABLE command.

To create an invisible index, the following syntax is used:

CREATE INDEX index_name ON table_name (c1, c2...) INVISIBLE;

To change the visibility of existing indexes, the following syntax in used:

ALTER TABLE table_name ALTER INDEX index_name [VISIBLE | INVISIBLE];

Subscribe to upGrad's Newsletter

Join thousands of learners who receive useful tips

Promise we won't spam!

Before presenting insights, you need to accurately assess patterns in data. This is where upGrad’s free Analyzing Patterns in Data and Storytelling course can help you. You will learn pattern analysis, insight creation, Pyramid Principle, logical flow, and data visualization. It’ll help you transform raw data into compelling narratives.

Also Read: SQL For beginners: Your Cheat Sheet for Faster Databases

Now, let’s look at some of the tips you can follow to improve performance of your index in MySQL.

Best Practices to Follow When Creating Indexes in MySQL

Creating indexes in MySQL can greatly enhance query performance, but if done incorrectly, it can also lead to increased storage usage and slower write operations.

To optimize index performance and ensure efficient database management, here are five best practices to follow when creating indexes in MySQL:

1. Use Indexes on Columns Frequently Used in WHERE Clauses

Indexing columns that are frequently used in WHERE clauses allows MySQL to quickly filter data, reducing query time. This is especially important for large datasets where searching through every row would be inefficient.

Example: If you frequently query the users table to find records based on email, create an index on the email column:

CREATE INDEX idx_email ON users(email);

This index will speed up queries like:

SELECT * FROM users WHERE email = 'user@example.com';

2. Use Composite Indexes for Multi-Column Queries

If your queries filter or sort data based on multiple columns, consider using composite indexes (indexes on multiple columns). Composite indexes are more efficient than creating multiple single-column indexes because they allow MySQL to use a single index to optimize queries.

Example: If you frequently query a sales table based on both store_id and date, create a composite index:

CREATE INDEX idx_store_date ON sales(store_id, date);

This index is optimized for queries like:

SELECT * FROM sales WHERE store_id = 1 AND date BETWEEN '2025-01-01' AND '2025-01-31';

3. Avoid Over-Indexing

While indexes improve query speed, too many indexes on a table can reduce write performance. Each time a row is inserted, updated, or deleted, MySQL must update all the indexes associated with the table. Be strategic about which columns to index and avoid indexing columns that do not frequently appear in queries.

Example: Instead of indexing every column, focus on columns that are frequently involved in queries. For example, indexing email and username in a users table, but not last_login (if it is rarely used in queries), could be more efficient:

CREATE INDEX idx_email_username ON users(email, username);

4. Use Indexes for Sorting and Joining Columns

Indexes are especially helpful when sorting (ORDER BY) or performing JOIN operations. By indexing the columns involved in these operations, MySQL can quickly retrieve the sorted or joined data.

Example: If you often join two tables based on the user_id column, it’s beneficial to create an index on the user_id column in both tables:

CREATE INDEX idx_user_id ON users(user_id);
CREATE INDEX idx_user_id_orders ON orders(user_id);

This index will optimize queries like:

SELECT * FROM users u
JOIN orders o ON u.user_id = o.user_id
WHERE u.status = 'active'
ORDER BY o.order_date DESC;

5. Monitor and Drop Unused Indexes

Over time, some indexes may become unused or redundant, negatively affecting performance. Regularly review your indexes using tools like pt-index-usage from Percona to identify indexes that aren’t being used. Dropping unnecessary indexes can free up space and reduce the overhead of maintaining them.

Example: If you discover that an index on a middle_name column in the users table is never used, you can drop it:

DROP INDEX idx_middle_name ON users;

This will help improve performance by eliminating unnecessary overhead.

Ensure to carefully monitor index usage and consider query patterns when deciding where and how to apply indexes.

Also Read: SQL Server: What You Should Know About How It's Built

Next, let’s look at how upGrad can help you learn how to create and manage index in MySQL.

Conclusion

Knowing how to create indexes in MySQL means you’re already a step ahead in the job market. Companies are always looking for people who can make their databases run faster and more efficiently, and indexing is a key skill that can set you apart. Plus, it’s a topic that often comes up in technical interviews for data and backend roles.

If you want to sharpen your MySQL skills, upGrad can help you get there. Their hands-on courses walk you through index creation and advanced optimization, so you’ll feel confident tackling real-world database challenges.

In addition to the courses covered above in the blog, here are some programs that can help you in your learning journey:

If you're unsure where to begin or which area to focus on, upGrad’s expert career counselors can guide you based on your goals. You can also visit a nearby upGrad offline center to explore course options, get hands-on experience, and speak directly with mentors! 

Boost your career with our popular Software Engineering courses, offering hands-on training and expert guidance to turn you into a skilled software developer.

Master in-demand Software Development skills like coding, system design, DevOps, and agile methodologies to excel in today’s competitive tech industry.

Stay informed with our widely-read Software Development articles, covering everything from coding techniques to the latest advancements in software engineering.

References: 
https://www.alibabacloud.com/blog/deep-dive-into-mysql-indexing-strategies_601595
https://ai2sql.io/sql-indexing-best-practices-speed-up-your-queries
https://www.devart.com/dbforge/mysql/studio/mysql-create-index.html

Frequently Asked Questions (FAQs)

1. Why does my composite index work for some WHERE clauses but not others even when all columns are indexed?

Composite indexes in MySQL follow the leftmost prefix rule, meaning the index can only be used if your query includes the leftmost column(s) in the index definition. For example, if you have an index on (col1, col2, col3), queries filtering on col1 or col1+col2 will use the index, but queries filtering only on col2 or col3 won't. MySQL reads indexes from left to right and cannot skip columns in the middle. To optimize queries that filter on different column combinations, you may need multiple indexes or reorder your composite index columns based on query patterns.

2. How can I determine if my index is actually being used when I have multiple similar indexes on the same table?

Use EXPLAIN or EXPLAIN ANALYZE to see which index MySQL's optimizer chooses, and check the key_len value to understand how much of a composite index is utilized. The Handler_read_* status variables show index efficiency after running queries, while sys.schema_unused_indexes view identifies completely unused indexes. MySQL's optimizer sometimes chooses different indexes than expected based on cardinality statistics. Use FORCE INDEX hints temporarily during testing to compare performance with specific indexes.

3. What happens to index performance when I frequently UPDATE columns that are part of an index?

Every UPDATE operation on indexed columns requires MySQL to maintain the index structure, significantly impacting write performance, especially with multiple indexes on frequently updated columns. B-tree indexes need rebalancing when values change, and this overhead multiplies with each additional index. Consider using covering indexes to reduce table lookups, which can offset some performance loss. For high-frequency update scenarios, evaluate whether certain indexes are worth the maintenance cost, or consider partitioning strategies to distribute the update load.

4. Can I create an index on a column that contains mostly NULL values, and will it be effective?

Yes, you can create indexes on columns with many NULL values, but their effectiveness depends on your query patterns. MySQL stores NULLs in indexes, but if 90% of your column values are NULL, the index primarily helps queries searching for NULL or NOT NULL conditions. For queries filtering on non-NULL values, the index can still be beneficial if it significantly reduces the dataset size. However, consider the storage overhead and maintenance cost versus the query performance gain, and evaluate partial indexes for such scenarios.

5. Why does my query performance degrade after adding what should be a helpful index?

This typically occurs due to index maintenance overhead, optimizer confusion with too many index choices, or outdated statistics. When you add an index, MySQL needs to maintain it during write operations, which can slow down INSERT/UPDATE/DELETE performance if your workload is write-heavy. The optimizer might also choose a suboptimal index when multiple options exist, or avoid a better execution plan it was using before. Run ANALYZE TABLE to update statistics, use EXPLAIN to verify the optimizer's choice, and consider dropping redundant indexes.

6. How do I handle indexing for queries that use both equality and range conditions in the WHERE clause?

Place equality conditions first in your composite index, followed by range conditions, because MySQL can only use one range condition per index efficiently. For example, with a query filtering on status='active' AND created_date BETWEEN dates, create an index on (status, created_date). This allows MySQL to seek directly to 'active' status rows and then scan the range within that subset. If you have multiple range conditions, consider separate indexes or restructuring your queries, and leverage Index Condition Pushdown for better performance.

7. What's the difference between using FORCE INDEX and optimizer hints, and when should I use each?

FORCE INDEX makes MySQL use a specific index regardless of cost estimates, while optimizer hints like USE_INDEX and IGNORE_INDEX provide more granular control and work with the optimizer rather than overriding it completely. Use FORCE INDEX only when you're certain the optimizer is making a poor choice and you've verified through testing that your chosen index performs better. Optimizer hints are preferable because they guide the optimizer while still allowing cost-based decisions. Both should be temporary solutions while you investigate why the optimizer isn't choosing the optimal path naturally.

8. How can I optimize indexes for queries that frequently use ORDER BY with LIMIT?

Create indexes that match your ORDER BY clause exactly to avoid filesort operations, especially crucial for LIMIT queries since MySQL can stop reading once it finds enough matching rows. For queries with WHERE conditions and ORDER BY, place WHERE columns first for selectivity, then ORDER BY columns, but test both arrangements since ORDER BY-first indexes sometimes perform better for LIMIT queries. Consider DESC indexes in MySQL 8.0+ if you frequently sort in descending order. The optimizer can use an index backwards, but explicit DESC indexes are more efficient for large result sets.

9. Why do my indexes show different cardinality values when I run SHOW INDEXES multiple times?

MySQL's index cardinality statistics are estimates based on sampling, not exact counts, and they're updated periodically or when you run ANALYZE TABLE. The storage engine samples random pages to estimate uniqueness, so slight variations are normal, but significantly outdated statistics can lead to poor optimizer decisions. Run ANALYZE TABLE after substantial data changes to refresh statistics and check the innodb_stats_sample_pages variable to understand sampling behavior. For critical queries, consider optimizer hints if statistics inconsistency causes performance issues, but focus on keeping statistics current.

10. How do I determine the optimal order of columns in a composite index when I have complex queries with multiple WHERE conditions?

Analyze your query patterns first, then apply the general rule: equality conditions first (most selective), then range conditions, then ORDER BY columns. Use the selectivity formula COUNT(DISTINCT column) / COUNT(*) to determine which equality columns should come first - higher selectivity generally goes first. However, real-world testing often trumps theoretical optimization because MySQL's optimizer considers data distribution and correlation between columns. Create test indexes with different column orders and use EXPLAIN to compare execution plans, prioritizing frequently used query patterns over less common ones.

11. What are the implications of using AUTO_INCREMENT columns as part of composite indexes versus having them as separate indexes?

AUTO_INCREMENT columns in composite indexes can create hotspots in high-concurrency environments because all new inserts target the same index page, leading to contention and reduced insert performance. However, they provide excellent clustering benefits for related data and are great for range queries when combined with other columns. If your queries frequently filter by AUTO_INCREMENT ID along with other columns, composite indexes make sense despite the insert overhead. For high-concurrency OLTP systems, consider UUID or distributed ID generation strategies, and monitor for metadata lock waits and page-level contention in performance_schema.

Rohan Vats

408 articles published

Rohan Vats is a Senior Engineering Manager with over a decade of experience in building scalable frontend architectures and leading high-performing engineering teams. Holding a B.Tech in Computer Scie...

Get Free Consultation

+91

By submitting, I accept the T&C and
Privacy Policy

India’s #1 Tech University

Executive PG Certification in AI-Powered Full Stack Development

77%

seats filled

View Program

Top Resources

Recommended Programs

upGrad

upGrad KnowledgeHut

Professional Certificate Program in UI/UX Design & Design Thinking

#1 Course for UI/UX Designers

Bootcamp

3 Months

upGrad

upGrad

AI-Driven Full-Stack Development

Job-Linked Program

Bootcamp

36 Weeks

IIIT Bangalore logo
new course

Executive PG Certification

9.5 Months