Databases 9 min read

SQL Query Optimization: Cutting a 9M‑Row Scan from 17 s to 300 ms

The article analyzes why a MySQL LIMIT OFFSET query on a 9.5 million‑row table takes 16 seconds, demonstrates how moving the filter into a sub‑query that returns only primary‑key IDs and joining back reduces execution to 0.35 seconds, and validates the theory by measuring InnoDB buffer‑pool page accesses.

Smart Sea Tide
Smart Sea Tide
Smart Sea Tide
SQL Query Optimization: Cutting a 9M‑Row Scan from 17 s to 300 ms

Problem

A financial transaction table with 9,555,695 rows (MySQL 5.7.17) used a simple SELECT … FROM `table_name` LIMIT 0,10 query. The query took 16 s 831 ms to execute because MySQL processes LIMIT offset, row_count by scanning index leaf nodes up to offset + row_count, fetching each corresponding clustered row, and discarding the first offset rows.

Original Query

SELECT <em>...</em>
FROM `table_name`
WHERE <em>conditions</em>
LIMIT 0,10;

Running a high‑offset query such as SELECT * FROM test WHERE val=4 LIMIT 300000,5 forced MySQL to read 300,005 index entries and 300,005 clustered rows, resulting in massive random I/O and a runtime of 15.98 s.

Optimized Query

SELECT <em>...</em>
FROM `table_name` main_table
RIGHT JOIN (
    SELECT id
    FROM `table_name`
    WHERE <em>conditions</em>
    LIMIT 0,10
) temp_table ON temp_table.id = main_table.id;

The rewrite moves the filter into a sub‑query that selects only the primary‑key id, then joins back to fetch the remaining columns. Execution time dropped to 163 ms (total 347 ms including fetching).

Why LIMIT Causes Slowness

MySQL does not know in advance which index entries will satisfy the offset, so it must walk the index sequentially. For each index leaf node it performs a “回表” (back‑table) lookup on the clustered index to retrieve the full row, even for rows that will later be discarded. This results in a number of index‑leaf and clustered‑row lookups equal to offset + row_count.

Experiment Setup

MySQL version: SELECT VERSION();5.7.17 Table schema:

+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| val   | int(10) unsigned    | NO   | MUL | 0       |                |
| source| int(10) unsigned    | NO   |     | 0       |                |
+-------+---------------------+------+-----+---------+----------------+

Inserted 5,242,882 rows.

To obtain a clean buffer pool before each test, MySQL was restarted with innodb_buffer_pool_dump_at_shutdown=0 and innodb_buffer_pool_load_at_startup=0.

Verification Method

After each query, the number of data and index pages loaded into the InnoDB buffer pool was counted:

SELECT index_name, COUNT(*)
FROM information_schema.INNODB_BUFFER_PAGE
WHERE INDEX_NAME IN ('val','PRIMARY')
  AND TABLE_NAME LIKE '%test%'
GROUP BY index_name;

Results

Original high‑offset query ( LIMIT 300000,5) loaded 4,098 data pages and 208 index pages.

Optimized sub‑query + join loaded only 5 data pages and 390 index pages.

Running the optimized query returned the same 5 rows in 0.38 s, while the original query required 15.98 s.

Conclusion

For pagination with large offsets, rewriting the query to first fetch primary‑key IDs in a sub‑query and then join back dramatically reduces the number of back‑table lookups, random I/O, execution time, and buffer‑pool pollution.

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.

SQLQuery OptimizationInnoDBMySQLBuffer PoolLIMIT Offset
Smart Sea Tide
Written by

Smart Sea Tide

Sharing cutting‑edge big data and AI technologies, with occasional lifestyle insights.

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.