Optimizing MySQL LIMIT Queries by Reducing Unnecessary Row Scans
This article explains why using a large OFFSET with MySQL LIMIT can cause severe performance degradation, demonstrates the problem with a real‑world 9.5 million‑row table, and shows how rewriting the query with a sub‑query that selects only primary keys can cut execution time from seconds to milliseconds.
In a table with 9,555,695 rows, a query using SELECT * FROM test WHERE val=4 LIMIT 300000,5 took 16 s 938 ms because MySQL had to scan 300,005 index entries and corresponding clustered rows before discarding the first 300,000 rows.
The author proposes moving the LIMIT into a sub‑query that retrieves only the primary‑key IDs, then joining back to the main table, which reduces the execution time to 347 ms (execution 163 ms, fetching 184 ms).
Original SQL (slow):
-- 优化前SQL
SELECT various_fields
FROM `table_name`
WHERE various_conditions
LIMIT 0,10;Optimized SQL (fast):
-- 优化后SQL
SELECT various_fields
FROM `table_name` main_table
RIGHT JOIN (
SELECT id -- sub‑query only selects primary key
FROM `table_name`
WHERE various_conditions
LIMIT 0,10
) temp_table ON temp_table.id = main_table.id;The performance gain comes from eliminating the costly back‑table lookups: the original query reads the index leaf nodes, then for each matching row fetches the full row from the clustered index, resulting in massive random I/O. The rewritten query fetches only the needed primary keys, then retrieves the corresponding rows in a single join, dramatically reducing I/O.
To verify the hypothesis, the author examined InnoDB buffer‑pool statistics. The slow query loaded 4,098 data pages and 208 index pages, while the optimized join loaded only 5 data pages and 390 index pages, confirming far fewer page reads.
Additional steps include clearing the buffer pool on MySQL restart (disabling innodb_buffer_pool_dump_at_shutdown and innodb_buffer_pool_load_at_startup) to ensure accurate measurements.
References: 1. https://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/ 2. https://dev.mysql.com/doc/refman/5.7/en/innodb-information-schema-buffer-pool-tables.html
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
