DBAtlas · 数据库运维图谱

行数限制 / 分页(LIMIT/OFFSET、FETCH、ROWNUM、TOP)

Oracle

-- 12c+ standard: OFFSET/FETCH
SELECT name, salary FROM employee
ORDER BY salary DESC
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

-- Older versions: with ROWNUM
SELECT * FROM (
  SELECT name, salary FROM employee ORDER BY salary DESC
) WHERE ROWNUM <= 10;

用于限制结果集或分页。自 Oracle 12c 起支持标准的 OFFSET n ROWS FETCH NEXT m ROWS ONLY。此前使用 ROWNUM 伪列;由于 ROWNUM 在排序之前分配,必须外包一层带 ORDER BY 的子查询。

PostgreSQL

-- LIMIT/OFFSET
SELECT name, salary FROM employee
ORDER BY salary DESC
LIMIT 10 OFFSET 20;

-- Standard equivalent: FETCH
SELECT name, salary FROM employee
ORDER BY salary DESC
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

PostgreSQL 同时支持 LIMIT n OFFSET m 和标准的 OFFSET ... FETCH 形式。OFFSET 值很大时速度慢;深度分页使用基于键的(keyset / 'WHERE id > last_id')分页更高效。没有 ORDER BY 的 LIMIT 不保证结果顺序。

MySQL

-- LIMIT [offset,] row_count
SELECT name, salary FROM employee
ORDER BY salary DESC
LIMIT 10 OFFSET 20;

-- Short form: LIMIT offset, row_count
SELECT name, salary FROM employee ORDER BY salary DESC LIMIT 20, 10;

MySQL/MariaDB 以两种形式使用 LIMIT 关键字:LIMIT row_count OFFSET offset 或 LIMIT offset, row_count。MySQL 8.0.19+ 也接受标准的 FETCH 语法。为解决深度 OFFSET 的性能问题,推荐使用 keyset 分页。

SQL Server

-- First N with TOP
SELECT TOP 10 name, salary FROM employee ORDER BY salary DESC;

-- OFFSET/FETCH for paging (2012+), ORDER BY mandatory
SELECT name, salary FROM employee
ORDER BY salary DESC
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

SQL Server 使用 TOP n(及 TOP (n) PERCENT / WITH TIES 变体)获取前 N 行,自 2012 起使用 OFFSET ... FETCH 进行分页。OFFSET/FETCH 必须配合 ORDER BY 才能工作。SQL Server 没有 LIMIT 关键字。

MongoDB

// Paging with skip/limit
db.employee.find()
  .sort({ salary: -1 })
  .skip(20)
  .limit(10)

在 MongoDB 中,limit() 设置返回的文档数,skip() 设置跳过的文档数;与 sort() 结合即可实现分页。skip 值很大时开销高;深度分页推荐基于最后一个已见值的范围(keyset)查询。

Redis

# Range read on a sorted set (ZSET):
ZREVRANGE salary_sorted 20 29    # members ranked 21-30
# Range on a list:
LRANGE queue 0 9              # first 10 elements

Redis 没有 SQL LIMIT,但有范围读取命令:Sorted Set 使用 ZRANGE/ZREVRANGE start stop(基于索引)或 ZRANGEBYSCORE ... LIMIT offset count;List 使用 LRANGE。这些命令提供类似分页的访问方式。

Elasticsearch

GET employee/_search
{
  "from": 20,
  "size": 10,
  "sort": [ { "salary": "desc" } ]
}

在 Elasticsearch 中,'size' 设置返回的命中数,'from' 设置跳过的数量(等价于 LIMIT/OFFSET)。from+size 最多为 index.max_result_window(默认 10,000);深度分页使用 'search_after'(keyset)或 PIT(point-in-time)。

在 DBAtlas 中打开 →