Computer >> 컴퓨터 >  >> 프로그래밍 >> MySQL

MySQL에서 대용량 SELECT 결과를 청크 단위로 나누어 조회하는 방법

MySQL에서 대용량 데이터를 청크로 조회하는 이유

테이블에 수천, 수만 건의 레코드가 저장되어 있을 때 전체 데이터를 한 번에 SELECT하면 메모리 부하와 응답 지연이 발생할 수 있습니다. 이럴 때 ORDER BY와 LIMIT 절을 조합하면 데이터를 원하는 크기의 청크(chunk) 단위로 나누어 효율적으로 조회할 수 있습니다.

기본 문법: ORDER BY와 LIMIT 활용하기

대용량 SELECT 결과를 청크 단위로 가져오려면 다음과 같은 기본 문법을 사용합니다.

SELECT * FROM yourTableName ORDER BY yourColumnName LIMIT 0,10;

위 쿼리는 테이블에서 10개의 행을 반환합니다. LIMIT의 첫 번째 값인 0은 결과 집합의 시작 위치를 의미하며, 0부터 시작하는 인덱스(제로 인덱스) 방식입니다. 두 번째 값인 10은 한 번에 가져올 최대 행 수입니다.

다음 구간의 데이터 조회하기

11번째부터 30번째까지의 행을 가져오려면 LIMIT 값을 다음과 같이 조정합니다.

SELECT * FROM yourTableName ORDER BY yourColumnName LIMIT 10,20; -- 11번째부터 30번째까지

31번째부터 50번째까지의 행이 필요하다면 같은 방식으로 LIMIT을 설정합니다.

SELECT * FROM yourTableName ORDER BY yourColumnName LIMIT 30,20; -- 31번째부터 50번째까지

임시 테이블(Temporary Table)을 활용한 청크 처리

원본 테이블에 매번 정렬 연산을 반복 실행하는 것은 비효율적일 수 있습니다. 이 경우 임시 테이블을 만들어 데이터를 미리 저장해 두고, 임시 테이블에서 LIMIT으로 필요한 만큼씩 조회하는 방법이 좋습니다.

1단계: 임시 테이블 생성

DROP TEMPORARY TABLE IF EXISTS yourTemporaryTableName;
CREATE TEMPORARY TABLE yourTempTableName
AS
(
SELECT * FROM yourOriginalTableName
ORDER BY Id
LIMIT 0,100
);

2단계: 임시 테이블에서 청크 단위로 조회

모든 레코드가 임시 테이블에 저장되었다면, 앞서 설명한 LIMIT 방식으로 자유롭게 데이터를 가져올 수 있습니다.

SELECT * FROM yourTemporaryTableName LIMIT 0,100;
SELECT * FROM yourTemporaryTableName LIMIT 100,1000;

3단계: 작업 완료 후 임시 테이블 삭제

LIMIT 값은 상황에 맞게 직접 설정하면 됩니다. 모든 작업이 끝나면 불필요한 리소스 낭비를 막기 위해 임시 테이블을 삭제하는 것이 좋은 습관입니다.

DROP TEMPORARY TABLE yourTemporaryTableName;

실전 예제로 확인하기

지금까지 설명한 내용을 실제 예제로 살펴보겠습니다. 먼저 테스트용 테이블을 생성합니다.

mysql> create table getRecordsDemo
-> (
-> Id int NOT NULL AUTO_INCREMENT,
-> PRIMARY KEY(Id)
-> );
Query OK, 0 rows affected (1.68 sec)

INSERT 명령으로 다수의 샘플 레코드를 삽입합니다.

mysql> insert into getRecordsDemo values(),(),(),(),(),(),(),(),(),(), ... ;
Query OK, 738 rows affected (0.34 sec)
Records: 738 Duplicates: 0 Warnings: 0

총 738개의 레코드가 생성되었습니다. 이제 위에서 설명한 것처럼 임시 테이블을 생성합니다.

mysql> drop temporary table if exists TempRecord;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> create temporary table TempRecord
-> as
-> (
-> select * from getRecordsDemo order by Id limit 0,738
-> );
Query OK, 738 rows affected (0.03 sec)
Records: 738 Duplicates: 0 Warnings: 0

이제 LIMIT 절을 사용해 청크 단위로 결과를 조회할 수 있습니다.

케이스 1: 첫 번째 청크(1~10행) 조회

임시 테이블 'TempRecord'에서 일부 레코드를 가져오는 쿼리는 다음과 같습니다.

mysql> select * from TempRecord limit 0,10;

실행 결과:

+----+
| Id |
+----+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
+----+
10 rows in set (0.00 sec)

케이스 2: 두 번째 청크(11~30행) 조회

다음 구간의 레코드를 가져오는 쿼리입니다.

mysql> select * from TempRecord limit 10,20;
+----+
| Id |
+----+
| 11 |
| 12 |
| 13 |
| 14 |
| 15 |
| 16 |
| 17 |
| 18 |
| 19 |
| 20 |
| 21 |
| 22 |
| 23 |
| 24 |
| 25 |
| 26 |
| 27 |
| 28 |
| 29 |
| 30 |
+----+
20 rows in set (0.00 sec)

케이스 3: 세 번째 청크(31~50행) 조회

그다음 구간의 레코드도 동일한 방식으로 조회합니다.

mysql> select * from TempRecord limit 30,20;
+----+
| Id |
+----+
| 31 |
| 32 |
| 33 |
| 34 |
| 35 |
| 36 |
| 37 |
| 38 |
| 39 |
| 40 |
| 41 |
| 42 |
| 43 |
| 44 |
| 45 |
| 46 |
| 47 |
| 48 |
| 49 |
| 50 |
+----+
20 rows in set (0.00 sec)

정리

MySQL에서 대용량 SELECT 결과를 처리할 때는 ORDER BY + LIMIT 조합으로 페이지네이션하듯 청크 단위로 데이터를 가져오는 것이 핵심입니다. 특히 원본 테이블의 정렬 비용을 줄이고 싶다면 임시 테이블을 활용해 한 번만 정렬한 뒤 여러 번 조회하는 방식이 성능 면에서 유리합니다. 작업이 끝난 후에는 반드시 임시 테이블을 DROP하여 세션 리소스를 정리하는 것을 잊지 마세요.