행 제한 / 페이징(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는 첫 N개 행에 TOP n(TOP (n) PERCENT / WITH TIES 변형 포함)을, 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 elementsRedis에는 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'는 반환할 hit 수를, 'from'은 건너뛸 수를 지정한다(LIMIT/OFFSET에 해당). from+size는 최대 index.max_result_window(기본값 10,000)까지 가능하며, 깊은 페이징에는 'search_after'(keyset)나 PIT(point-in-time)를 사용한다.