Databases 8 min read

Why Adding LIMIT 1 Can Make MySQL Queries 50× Slower—and How to Fix It

Adding a LIMIT 1 clause to a MySQL query that fetches the latest order for a user can unexpectedly trigger a full‑table scan, slowing execution by up to 50 times; this article explains the optimizer’s mis‑choice, shows EXPLAIN analysis, and offers three practical remedies.

Su San Talks Tech
Su San Talks Tech
Su San Talks Tech
Why Adding LIMIT 1 Can Make MySQL Queries 50× Slower—and How to Fix It

When writing SQL, many developers habitually add LIMIT 1 to queries that only need a single row, assuming it will reduce I/O and CPU. However, a recent production incident showed that adding LIMIT 1 made a query 50 times slower.

Reproducing the Issue

The business requirement was to retrieve the most recent "processing" order for a specific user. The orders table contains about 5 million rows and has two key indexes:

idx_user_status ( (user_id, status)) – filters by user and status.

idx_create_time ( (create_time)) – supports ordering by time.

The original SQL was:

SELECT id, order_no, amount
FROM orders
WHERE user_id = 10086 AND status = 1
ORDER BY create_time DESC
LIMIT 1;

Deployed to production, this query triggered a slow‑query alert and took 2.5 seconds . Removing the LIMIT 1 and running the same query without it reduced the execution time to about 50 ms .

Analyzing with EXPLAIN

Running EXPLAIN on both statements revealed the optimizer’s choices:

Without LIMIT: MySQL used idx_user_status, quickly filtering the few dozen rows that match the user and status, then sorting them in memory.

With LIMIT 1: MySQL abandoned the filtering index and chose idx_create_time, scanning the table in descending order of create_time and checking each row for the user and status condition.

The optimizer assumed it would find a matching row early in the time‑ordered scan, but because the target user’s latest qualifying order was over a year old, it had to scan more than 2 million rows before finding it.

Why the Optimizer Made the Wrong Choice

The optimizer evaluates two abstract plans:

Plan A – Filter Index First: Use idx_user_status to locate all matching rows, then sort them. This is efficient when many rows match the filter.

Plan B – Time Index + LIMIT: Use idx_create_time to read rows in the required order and stop after the first match. This avoids a separate sort but relies on the assumption that a matching row appears early.

In this case, the optimizer “bet” that Plan B would find a match quickly, but the data distribution (a sparse recent match) caused the bet to fail, resulting in a full‑table‑scan‑level slowdown.

How to Fix the Problem

Three practical solutions are presented:

1. Force the Desired Index

Use FORCE INDEX (idx_user_status) to tell MySQL to use the filtering index regardless of the LIMIT:

SELECT ... FROM orders FORCE INDEX (idx_user_status) ...;

This immediately restores the fast execution path, though it ties the query to a specific index name.

2. Create a Composite Index

Build an index that satisfies both the filter and the ordering: (user_id, status, create_time) With this index, MySQL can locate the relevant rows and retrieve them already sorted, eliminating the need for a separate sort and avoiding the optimizer’s mis‑choice.

3. Use a Subquery to Isolate LIMIT

If changing the schema is not possible, rewrite the query so that the inner subquery uses the filtering index, and the outer query applies LIMIT 1:

SELECT * FROM (
  SELECT ... FROM orders
  WHERE user_id = 10086 AND status = 1
  ORDER BY create_time DESC
) AS tmp
LIMIT 1;

This prevents the LIMIT clause from influencing the inner index selection.

Takeaway

While LIMIT 1 is generally a good habit, it can backfire when the optimizer’s cost model mis‑estimates data distribution. Whenever a query with LIMIT becomes unexpectedly slow, run EXPLAIN to inspect the chosen plan and consider forcing an index, adding a composite index, or restructuring the query.

PerformanceQuery OptimizationMySQLLIMITindexEXPLAIN
Su San Talks Tech
Written by

Su San Talks Tech

Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.

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.