Anand Singh
Oct 7, 2026
How to Fix a Slow MySQL Server
Fix a slow MySQL server without throwing in more CPU or RAM
How to Fix a Slow MySQL Server
A slow MySQL server doesn't always mean you need a bigger server. Your database might be fast and slow at the same time, depending upon load and pages being accessed, first thing in the fix it to measure latency of your database around the clock, you can use PieMonitor for that purpose.
In many cases, the real problem is a slow query, a missing index, inefficient schema design, too many connections, or a workload that isn't being monitored properly.
Before upgrading your database server, find out what is actually making MySQL slow.
This guide walks through a practical process for diagnosing and fixing MySQL performance problems.
- Find out what is actually slow
First, don't guess.
A MySQL server can feel slow for very different reasons:
- Queries are taking too long
- CPU usage is high
- Memory is exhausted
- Disk I/O is saturated
- There are too many connections
- Queries are waiting on locks
- The database is doing full table scans
- A missing index is causing unnecessary work
- The application is opening too many connections
- A table has grown much larger than expected
Start by looking at the server and MySQL metrics.
Useful things to monitor include:
- CPU usage
- RAM usage
- Disk usage
- Disk I/O
- Active connections
- Queries per second
- Slow queries
- Lock waits
- Temporary tables
- Buffer pool usage
The goal is simple:
Find the bottleneck before trying to fix it.
- Check for slow queries
One of the first things to investigate is whether MySQL is spending too much time executing specific queries.
Check the slow query log.
On many MySQL installations, you can inspect the current configuration with:
SHOW VARIABLES LIKE 'slow_query%';
You can also check the configured threshold:
SHOW VARIABLES LIKE 'long_query_time';
If the slow query log is disabled, enable it according to your MySQL deployment configuration.
For example:
SET GLOBAL slow_query_log = 'ON';
And configure an appropriate long_query_time.
For development or debugging, you might temporarily use a relatively low threshold such as:
SET GLOBAL long_query_time = 1;
This means queries taking longer than one second can be captured.
For production systems, choose the threshold based on your workload rather than blindly using one value.
- Use EXPLAIN
This is one of the most useful tools for diagnosing slow MySQL queries.
Suppose you have:
SELECT *
FROM users
WHERE email = 'user@example.com';
Run:
EXPLAIN
SELECT *
FROM users
WHERE email = 'user@example.com';
MySQL will show how it plans to execute the query.
Pay particular attention to:
- type
- possible_keys
- key
- rows
- Extra
A query doing a large table scan can become extremely expensive as the table grows.
For example, if MySQL reports:
type: ALL
it may be scanning the entire table.
That doesn't automatically mean the query is wrong, but it is worth investigating.
- Add the right index
One of the most common causes of slow queries is a missing or poorly designed index.
Imagine this query:
SELECT *
FROM orders
WHERE user_id = 12345;
If user_id isn't indexed, MySQL may need to inspect a large portion of the table to find matching rows.
Adding an index can dramatically reduce the amount of data MySQL needs to examine:
CREATE INDEX idx_orders_user_id
ON orders(user_id);
Then run EXPLAIN again.
You want to verify that MySQL can actually use the new index.
- Don't create indexes blindly
More indexes aren't always better.
Every index has a cost.
When you insert, update, or delete data, MySQL may also need to update the relevant indexes.
Too many indexes can therefore:
- Increase storage usage
- Increase write overhead
- Increase memory requirements
- Make writes slower
- Complicate query optimization
The goal isn't:
"Index everything."
The goal is:
Index the access patterns your application actually uses.
- Consider composite indexes
Sometimes a single-column index isn't enough.
Suppose your application frequently runs:
SELECT *
FROM orders
WHERE user_id = 12345
AND status = 'completed';
Instead of creating two separate indexes, you may benefit from a composite index:
CREATE INDEX idx_orders_user_status
ON orders(user_id, status);
The order of columns matters.
If your queries commonly filter by user_id and then status, the index can be designed around that access pattern.
Don't choose the column order randomly.
Look at the queries your application actually runs.
- Stop using SELECT * when you don't need it
This:
SELECT *
FROM users
WHERE id = 123;
may be perfectly fine for a small table.
But if the table contains many columns, large text fields, JSON data, or blobs, retrieving everything can become unnecessarily expensive.
Instead:
SELECT id, name, email
FROM users
WHERE id = 123;
This reduces the amount of data MySQL needs to read and send back to the application.
It can also reduce network traffic and application memory usage.
- Limit the amount of data you retrieve
Another common mistake is returning thousands of rows when the application only needs a few.
Instead of:
SELECT *
FROM orders
WHERE user_id = 12345;
consider:
SELECT id, total, created_at
FROM orders
WHERE user_id = 12345
ORDER BY created_at DESC
LIMIT 50;
For large datasets, pagination is usually better than loading everything at once.
- Be careful with OFFSET pagination
Traditional pagination often looks like this:
SELECT *
FROM orders
ORDER BY id
LIMIT 50 OFFSET 100000;
As the offset becomes larger, MySQL may need to walk past a large number of rows before returning the requested page.
For large datasets, consider cursor-based or keyset pagination.
For example:
SELECT *
FROM orders
WHERE id < 100000
ORDER BY id DESC
LIMIT 50;
This can be much more efficient when the relevant column is indexed.
- Check for missing indexes on JOINs
Slow joins are another common source of database performance problems.
For example:
SELECT orders.id, users.email
FROM orders
JOIN users
ON orders.user_id = users.id;
Make sure the columns involved in frequently executed joins are appropriately indexed.
Primary keys are indexed automatically, but foreign-key columns and other join columns may require their own indexes depending on the schema and query pattern.
- Check for functions on indexed columns
Queries can sometimes prevent efficient index usage by applying functions to columns.
For example:
SELECT *
FROM users
WHERE DATE(created_at) = '2026-10-07';
Depending on the query and index, this can make it harder for MySQL to use an index efficiently.
A range query is often better:
SELECT *
FROM users
WHERE created_at >= '2026-10-07 00:00:00'
AND created_at < '2026-10-08 00:00:00';
This preserves the ability to use an index on created_at.
- Look for lock contention
Sometimes the query itself isn't the problem.
Your query may simply be waiting for another transaction.
If your application suddenly becomes slow while CPU usage is relatively low, investigate locks and transactions.
Useful commands include:
SHOW PROCESSLIST;
and:
SHOW ENGINE INNODB STATUS;
Look for:
- Long-running transactions
- Lock waits
- Deadlocks
- Queries waiting on other transactions
A single transaction that stays open for too long can cause surprising problems elsewhere in the application.
- Check your connection count
Your application can also overwhelm MySQL by opening too many connections.
Check:
SHOW STATUS LIKE 'Threads_connected';
And:
SHOW VARIABLES LIKE 'max_connections';
A high connection count doesn't automatically mean something is wrong.
But if the application regularly approaches max_connections, investigate your connection management.
Use connection pooling where appropriate rather than creating a completely new database connection for every request.
- Check CPU usage
If MySQL is consistently consuming most of the available CPU, look for expensive queries.
A high CPU workload can be caused by:
- Full table scans
- Expensive joins
- Sorting large datasets
- Aggregations
- Poorly optimized queries
- Missing indexes
Don't immediately increase CPU.
First identify what MySQL is spending that CPU on.
- Check memory and InnoDB buffer pool
For InnoDB workloads, the buffer pool is one of the most important parts of MySQL memory configuration.
Check its current size:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
The buffer pool caches frequently accessed data and indexes in memory.
If your working dataset fits efficiently into memory, MySQL can avoid repeatedly reading data from disk.
But don't simply allocate all available RAM to MySQL.
Your operating system, connections, temporary tables, application processes, and other services also need memory.
- Check disk I/O
If CPU isn't particularly high but queries are still slow, disk I/O may be the bottleneck.
Check:
- Disk utilization
- Read/write latency
- IOPS
- Available disk space
- Storage throughput
Database workloads can be particularly sensitive to storage performance.
Moving from slow storage to faster SSD-backed storage can sometimes produce a significant improvement.
But again:
Measure first.
A faster disk won't fix a query that is unnecessarily scanning millions of rows.
- Watch for temporary tables and filesorts
Some queries require MySQL to create temporary tables or perform additional sorting.
Inspect query execution plans with:
EXPLAIN
and look at the Extra column.
Depending on the query, you may see things such as:
Using temporary
or:
Using filesort
These aren't automatically errors.
They simply tell you that MySQL is doing additional work.
If the query is slow, investigate whether the query structure or indexes can reduce that work.
- Don't increase MySQL configuration values blindly
A common reaction to database problems is to start changing:
max_connections
innodb_buffer_pool_size
tmp_table_size
max_heap_table_size
This can make things worse.
For example, increasing max_connections doesn't necessarily make MySQL handle more traffic efficiently.
It can actually increase memory pressure if many connections become active simultaneously.
Change configuration based on measured workload and resource usage.
- Find the worst queries first
Don't try to optimize everything.
Find the queries responsible for the majority of the database workload.
A useful optimization process is:
Find slow query
↓
Run EXPLAIN
↓
Understand execution plan
↓
Check indexes
↓
Rewrite query if necessary
↓
Test again
↓
Measure improvement
Repeat.
This is much more effective than randomly changing server settings.
- Measure before and after
Every performance change should have a measurable result.
Before:
Query time: 2.4 seconds
Rows examined: 1,200,000
After:
Query time: 35 ms
Rows examined: 120
Now you know the optimization worked.
Don't rely only on how the application "feels."
Measure the database.
A practical MySQL troubleshooting checklist
When someone tells you:
"Our MySQL server is slow."
Start here:
Step 1
Check CPU, RAM and disk I/O.
Step 2
Check active connections.
SHOW STATUS LIKE 'Threads_connected';
Step 3
Check slow queries.
SHOW VARIABLES LIKE 'slow_query%';
Step 4
Find the expensive query.
Step 5
Run:
EXPLAIN your_query;
Step 6
Check whether the query is using the expected indexes.
Step 7
Check how many rows MySQL is examining.
Step 8
Look for inefficient joins, sorting, temporary tables and large scans.
Step 9
Check for lock contention.
Step 10
Optimize the query or index.
Step 11
Measure again.
Step 12
Only then consider upgrading the server.
Should you upgrade your MySQL server?
Sometimes the answer is yes.
If you've optimized the queries, indexes and schema and the workload is genuinely exceeding the machine's capacity, you may need:
- More CPU
- More RAM
- Faster storage
- Read replicas
- Database partitioning
- Caching
- Better connection pooling
- Horizontal scaling
But scaling hardware should usually come after understanding the workload.
A bigger server can hide a bad query.
It doesn't fix it.
The $0 optimization
The cheapest database optimization is often not a new server.
It's finding the query that's doing unnecessary work.
Before spending another $100 or $500 per month on infrastructure, run:
EXPLAIN
Find the expensive query.
Check the indexes.
Measure the rows examined.
Then optimize.
Sometimes a single index can do more for your database than doubling the server's CPU.
Final takeaway
When MySQL is slow, don't start by asking:
"How much bigger should my server be?"
Start by asking:
"What is MySQL spending its time doing?"
Monitor the server.
Find the expensive queries.
Use EXPLAIN.
Fix indexes and query patterns.
Check locks and connections.
Measure the result.
Then scale the infrastructure when the workload actually requires it.
Optimize first. Scale second.
For help with your PieDB, reach out to Pie.host support.
