대량의 데이터를 다룰 때 전체 결과를 한꺼번에 가져오지 않고 일정한 크기(배치) 단위로 나누어 조회하면 메모리 사용량과 응답 속도 면에서 효율적입니다. MySQL에서는 LIMIT과 OFFSET 절을 활용해 이러한 배치 조회를 간단하게 구현할 수 있습니다.
LIMIT과 OFFSET의 기본 개념
LIMIT은 반환할 최대 행 수를 지정하고, OFFSET은 시작 위치까지 건너뛸 행 수를 지정합니다. 예를 들어 LIMIT 4 OFFSET 4는 앞의 4개 행을 건너뛴 후 그다음 4개 행만 가져옵니다.
예제 테이블 생성
먼저 실습에 사용할 테이블을 생성합니다.
mysql> create table DemoTable1514
-> (
-> Id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> FirstName varchar(20)
-> );
Query OK, 0 rows affected (0.63 sec)
샘플 데이터 삽입
INSERT 명령으로 총 10개의 레코드를 추가합니다.
mysql> insert into DemoTable1514(FirstName) values('Chris');
Query OK, 1 row affected (0.17 sec)
mysql> insert into DemoTable1514(FirstName) values('Bob');
Query OK, 1 row affected (0.12 sec)
mysql> insert into DemoTable1514(FirstName) values('Sam');
Query OK, 1 row affected (0.08 sec)
mysql> insert into DemoTable1514(FirstName) values('Mike');
Query OK, 1 row affected (0.09 sec)
mysql> insert into DemoTable1514(FirstName) values('Carol');
Query OK, 1 row affected (0.09 sec)
mysql> insert into DemoTable1514(FirstName) values('David');
Query OK, 1 row affected (0.12 sec)
mysql> insert into DemoTable1514(FirstName) values('Robert');
Query OK, 1 row affected (0.11 sec)
mysql> insert into DemoTable1514(FirstName) values('Adam');
Query OK, 1 row affected (0.12 sec)
mysql> insert into DemoTable1514(FirstName) values('John');
Query OK, 1 row affected (0.10 sec)
mysql> insert into DemoTable1514(FirstName) values('Jace');
Query OK, 1 row affected (0.13 sec)전체 레코드 확인
SELECT 문으로 테이블에 저장된 모든 레코드를 조회해 보겠습니다.
mysql> select * from DemoTable1514;
실행 결과는 다음과 같습니다.
+----+-----------+
| Id | FirstName |
+----+-----------+
| 1 | Chris |
| 2 | Bob |
| 3 | Sam |
| 4 | Mike |
| 5 | Carol |
| 6 | David |
| 7 | Robert |
| 8 | Adam |
| 9 | John |
| 10 | Jace |
+----+-----------+
10 rows in set (0.00 sec)
배치 단위로 행 선택하기
이제 핵심 쿼리입니다. LIMIT과 OFFSET을 조합하면 한 번에 하나의 배치(여기서는 4행)씩 조회할 수 있습니다.
mysql> select * from DemoTable1514 limit 4 offset 4;
실행 결과는 다음과 같습니다.
+----+-----------+
| Id | FirstName |
+----+-----------+
| 5 | Carol |
| 6 | David |
| 7 | Robert |
| 8 | Adam |
+----+-----------+
4 rows in set (0.00 sec)
결과 해석
총 10개의 행 중 OFFSET 4가 첫 번째부터 네 번째 행(Chris, Bob, Sam, Mike)을 건너뛰었고, LIMIT 4가 그다음 4개의 행(Carol, David, Robert, Adam)만 반환했습니다.
따라서 배치를 순차적으로 조회하려면 오프셋 값을 배치 크기만큼 계속 증가시키면 됩니다.
- 첫 번째 배치:
LIMIT 4 OFFSET 0→ 1~4번째 행 - 두 번째 배치:
LIMIT 4 OFFSET 4→ 5~8번째 행 - 세 번째 배치:
LIMIT 4 OFFSET 8→ 남은 9~10번째 행
참고 사항
테이블 규모가 매우 커지면 깊은 OFFSET 값은 내부적으로 불필요한 행을 모두 스캔해야 하므로 성능 저하가 발생할 수 있습니다. 이 경우 기준 키(예: Id 값)를 조건으로 사용하는 키셋 페이지네이션(Keyset Pagination)을 함께 고려하면 더 좋은 성능을 얻을 수 있습니다.