Databases 16 min read

Why Is MySQL Query Slow? Hidden Factors Beyond Indexes and How to Fix Them

This article explains why MySQL queries can become sluggish, covering the full query execution flow, profiling techniques, index pitfalls, connection‑pool limits, buffer‑pool sizing, and additional performance tricks, while providing concrete commands and code examples for each optimization step.

dbaplus Community
dbaplus Community
dbaplus Community
Why Is MySQL Query Slow? Hidden Factors Beyond Indexes and How to Fix Them

1. Database Query Process

A SQL statement goes through several stages: the client (written in Go, C++, etc.) opens a TCP connection, sends the query to MySQL, which first parses the statement for syntax errors, then the optimizer selects an index, and finally the executor calls the storage engine to fetch rows.

The storage engine (InnoDB by default) uses a buffer pool of 16 KB pages to cache data and index pages in memory, reducing disk I/O.

MySQL architecture
MySQL architecture

2. Slow Query Analysis

Enable profiling to see where time is spent:

mysql> set profiling=ON;
mysql> show variables like 'profiling';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| profiling     | ON    |
+---------------+-------+

After running a query, list recorded statements:

mysql> show profiles;
+----------+------------+---------------------------------------------------+
| Query_ID | Duration   | Query                                             |
+----------+------------+---------------------------------------------------+
| 1        | 0.06811025 | select * from user where age>=60                  |
| 2        | 0.00151375 | select * from user where gender = 2 and age = 80  |
| ...      | ...        | ...                                               |
+----------+------------+---------------------------------------------------+

Inspect a specific query:

mysql> show profile for query 1;
+----------------------+----------+
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000074 |
| checking permissions | 0.000010 |
| Opening tables       | 0.000034 |
| init                 | 0.000032 |
| System lock          | 0.000027 |
| optimizing           | 0.000020 |
| statistics           | 0.000058 |
| preparing            | 0.000018 |
| executing            | 0.000013 |
| Sending data         | 0.067701 |
| end                  | 0.000021 |
| query end            | 0.000015 |
| closing tables       | 0.000014 |
| freeing items        | 0.000047 |
| cleaning up          | 0.000027 |
+----------------------+----------+

The dominant cost is often the Sending data phase, which indicates the executor is reading many rows.

3. Index‑Related Causes

Use EXPLAIN to see which index is chosen and how many rows are scanned:

EXPLAIN SELECT * FROM user WHERE age>=60;

If the type column shows ALL, a full table scan occurs. Even when an index exists (e.g., idx_age), MySQL may ignore it if the index is non‑unique and requires a costly back‑lookup to the primary key.

Common index pitfalls:

Low selectivity (many rows share the same indexed value).

Prefix indexes that are too short.

Implicit type conversion or inequality operators that prevent index use.

Force the desired index when necessary:

SELECT * FROM user FORCE INDEX (idx_age) WHERE age>=60;

4. Insufficient Connections

MySQL’s default max_connections is 100 (max 16384). Increase it when the server side limits concurrency:

mysql> set global max_connections = 500;
mysql> show variables like 'max_connections';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 500   |
+-----------------+-------+

Application‑side connection pools (e.g., Go’s gorm) also need enough slots:

func Init() {
    db, _ := gorm.Open(mysql.Open(conn), config)
    sqlDB, _ := db.DB()
    sqlDB.SetMaxIdleConns(200)   // idle connections
    sqlDB.SetMaxOpenConns(1000)   // total connections
}

5. Buffer Pool Too Small

The InnoDB buffer pool caches data and index pages. A larger pool reduces disk reads. Check its size:

mysql> show global variables like 'innodb_buffer_pool_size';
+-------------------------+-----------+
| Variable_name           | Value     |
+-------------------------+-----------+
| innodb_buffer_pool_size | 134217728 |
+-------------------------+-----------+

Increase it (e.g., to 512 MB):

mysql> set global innodb_buffer_pool_size = 536870912;
mysql> show global variables like 'innodb_buffer_pool_size';
+-------------------------+-----------+
| Variable_name           | Value     |
+-------------------------+-----------+
| innodb_buffer_pool_size | 536870912 |
+-------------------------+-----------+

Monitor hit rate:

mysql> show status like 'Innodb_buffer_pool_%';

Hit rate = 1 - (Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests) * 100%. A rate above 99% is typical; lower values suggest enlarging the pool.

6. Other Tricks

MySQL 8.0 removed the query cache because it invalidates all cached results on any table change, making it unsuitable for frequently updated data.

7. Summary

Slow queries are often index‑related: wrong index, low selectivity, or massive row scans.

Too few client‑server connections limit concurrency; raise max_connections and enlarge application connection pools.

InnoDB buffer pool size and hit rate directly affect I/O; increase the pool if hit rate drops below ~99%.

Query cache can speed up read‑only workloads but is deprecated in modern MySQL versions.

Closing image
Closing image
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Connection PoolmysqlIndex OptimizationProfilingslow-querybuffer pool
dbaplus Community
Written by

dbaplus Community

Enterprise-level professional community for Database, BigData, and AIOps. Daily original articles, weekly online tech talks, monthly offline salons, and quarterly XCOPS&DAMS conferences—delivered by industry experts.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.