关键在于有合适索引+明确ORDER BY排序+LIMIT配合覆盖索引;仅SELECT * FROM t LIMIT 10通常无法避免全表扫描,必须通过EXPLAIN验证执行计划是否使用索引扫描。

在SQL中只查前10条记录且避免全表扫描,关键在于有合适的索引 + 明确的排序依据 + 使用 LIMIT/TOP/ROWNUM 等语法。没有 ORDER BY 的 LIMIT 很可能仍会触发全表扫描(尤其在无索引或统计信息不准时),因为数据库无法确定哪10条是“前10条”——它必须先拿到全部数据再截断。
必须配合 ORDER BY 和对应索引
仅写 SELECT * FROM t LIMIT 10 通常无法避免全表扫描,除非该表极小或优化器基于统计信息做了特殊处理(不可靠)。真正高效的方式是:
- 明确指定排序字段,例如
ORDER BY created_time DESC - 确保该排序字段上有有效索引(如
INDEX(created_time)或INDEX(status, created_time)) - 查询语句形如:
SELECT * FROM orders WHERE status = 'paid' ORDER BY created_time DESC LIMIT 10
此时数据库可利用索引快速定位并顺序读取前10条满足条件的行,无需扫描整张表。
避免 SELECT *,只查必要字段
即使有索引,若查询列未被覆盖,数据库仍需回表(Index Lookup + Table Access);若索引已包含所有需要的字段(覆盖索引),就能完全避免访问数据页:
- 差:
SELECT * FROM users ORDER BY id LIMIT 10→ 可能回表(取决于索引结构) - 好:
SELECT id, name, email FROM users ORDER BY id LIMIT 10,并建索引INDEX(id, name, email)
注意不同数据库的语法与行为差异
各数据库对“取前N条”的实现和优化支持略有不同:
-
MySQL / PostgreSQL:用
LIMIT 10,配合索引效果稳定 -
SQL Server:推荐用
TOP 10+ORDER BY,或更可控的OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY -
Oracle 12c+:用
FETCH FIRST 10 ROWS ONLY;老版本用ROWNUM ,但必须嵌套在带 ORDER BY 的子查询中,否则排序失效
验证是否真的避免了全表扫描
执行前务必看执行计划(EXPLAIN):
- MySQL:运行
EXPLAIN SELECT ... LIMIT 10,确认type是range或index,key显示用了哪个索引,rows接近10而非表总行数 - PostgreSQL:用
EXPLAIN (ANALYZE, BUFFERS),观察是否为Index Scan或Index Only Scan - 避免看到
Seq Scan(PostgreSQL)、ALL(MySQL)或TABLE ACCESS FULL(Oracle)










