개요
안녕하세요. 이 글은 AWS RDS S3 import/export 기능을 설명하고 import 성능 테스트한 결과를 공유합니다.
S3 import/export란?
RDS S3 import/export는 RDS 데이터를 S3로 내보내거나, S3 데이터를 RDS로 가져오는 기능입니다. RDS가 S3에 접근하려면 IAM role 연결 설정이 필요합니다. 이 기능은 모든 RDS에서 사용할 수 있는 것이 아니라 Aurora 계열 RDS만 지원합니다.

언제 S3 import/export를 쓰면 좋을까?
S3에 데이터를 저장하고 활용해야 할 때 S3 import/export를 사용하면 좋습니다. 예를 들어 RDS snapshot 대신 일부 데이터를 주기적으로 백업해야 하는 경우에 사용하거나, RDS migration을 진행할 때 S3를 공유 스토리지 역할로 활용할 수도 있습니다.
저는 RDS Point in Time Recovery 실행 후, 손상된 일부 데이터만 선택해서 복구할 때 S3 import와 export를 모두 사용했습니다.
Mysql INFILE import VS S3 import 성능 비교
MySQL Aurora db.r6i.xlarge 스펙으로 1,800만 건의 데이터를 import 성능테스트했습니다. 인덱스 등 데이터베이스 설정 없이 import 기능만 실행했습니다.
1,800만 건의 데이터는 이전 블로그에 정리했던 TPC-H를 사용했습니다.
LOAD DATA LOCAL INFILE과 LOAD DATA FROM S3 PREFIX import를 비교한 결과, INFILE import가 S3 import보다 약 12% 빨랐습니다. S3 import는 S3에 접근할 때 추가적인 네트워크 홉이 발생하여 INFILE 방식보다 성능이 낮게 측정된 것으로 보입니다.
- INFILE import

- S3 import

AWS 블로그에는 INFILE과 S3 import를 비교한 글이 없지만, INFILE import 성능이 매우 좋다고 설명합니다.

INFILE와 S3 import 성능을 더 정확히 비교하려면 수억 건의 데이터와 데이터베이스 설정을 해야 할 것 같습니다.
Postgres Aurora S3 import/export 설정과 Mysql Aurora 다른 점
1. 2025년 11월 기준 postgres aurora는 prefix s3 import가 없습니다.
mysql aurora에서는 prefix s3 import가 지원되서 abc_*같이 패턴이 있는 파일을 한번에 import할 수 있습니다. 하지만 postgres는 s3 import prefix가 지원되지 않아 병렬 import 로직을 개발해야 합니다.
2. RDS에 IAM attach할 때 설정이 다릅니다.
mysql aurora는 import, export에 사용하는 IAM role이 한개만 필요합니다.

반면, postgres aurora에 IAM attach를 할 때 import, export IAM role이 각각 필요합니다.

3. 파라미터 그룹 설정 차이가 있습니다.
Mysql Aurora는 S3 import/export를 사용하기 위해 파라미터 그룹을 설정이 필요했는데 Postgres Aurora는 파라미터 그룹을 설정하지 않습니다. Postgres Aurora는 aws_s3 extension을 사용합니다.
4. 인스턴스 재부팅 차이가 있습니다.
Mysql Aurora은 파라미터 변경된 사항을 적용하기 위해 RDS 인스턴스 재부팅이 필요합니다. 하지만, Postgres Aurora는 파라미터 그룹을 변경하지 안았기 때문에 RDS 인스턴스 재부팅이 필요 없습니다.
5. 파일 확장자 차이가 있습니다.
PostgreSQL는 S3 import/export할 때 MySQL과 달리 파일 형식을 명시적으로 지정해야 합니다. PostgreSQL은 CSV, TEXT, GZIP 압축 파일을 지원합니다.
mysql s3 버킷에 있는 파일은 확장자가 필요없지만 postgres s3버킷에는 확장자가 필요합니다. 또한, mysql은 prefix가 지원해서 버킷에 여러 파일을 업로드하여 import할 수 있지만 postgres는 prefix가 지원하지 않아 단일 파일을 업로드했습니다.'


6. database user의 권한 설정의 차이가 있습니다.
Mysql Aurora는 명시적으로 어떤 사용자에게 S3 import/export권한을 주는지 설정해야했지만, postgres는 user에게 권한을 설정하는게 없습니다. 왜냐하면, postgres는 role기반으로 권한을 설정하기 때문입니다.
예제코드
이 글에서 실습한 mysql aurora, postgres aurora는 테라폼으로 구축했으며 제 github에 공개되어 있습니다. public subnet에서 RDS를 구축했고 비밀번호가 테라폼에 노출되어 있으므로 절대 업무환경에서 사용하지 마세요. 개인공부로만 사용하세요
- github repo: https://github.com/choisungwook/portfolio/tree/master/aws/rds/s3_import
Mysql Aurora 설정
참고자료: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Integrating.LoadFromS3.html
1. RDS에 IAM role 연결
RDS 대시보드에서 Connectivity & security → Managed IAM roles에서 IAM role을 attach합니다.

IAM role의 policy는 아래처럼 설정합니다. S3 버킷이름을 변경해주세요.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::akubun-9umx9v5r"
},
{
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:PutObject",
"s3:DeleteObject",
"s3:AbortMultipartUpload",
"s3:ListMultipartUploadParts"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::akubun-9umx9v5r/*"
}
]
}

IAM role은 RDS가 assume할 수 있도록 Trust relationship을 설정합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AssumeRoleForBackup",
"Effect": "Allow",
"Principal": {
"Service": "rds.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}

RDS에 IAM role을 연결한 후 MySQL cluster parameter group을 수정합니다. "aws_default_s3_role"에 연결한 IAM role을 입력합니다. 설정을 완료한 후 RDS 인스턴스를 재부팅합니다.


2. Database user에게 S3 import/export 권한 부여
MySQL 사용자에게 S3 import/export 권한을 부여합니다. rds_root 사용자는 권한 설정이 필요하지 않습니다.
AWS_LOAD_S3_ACCESS 권한은 S3 import권한이고 AWS_SELECT_S3_ACCESS는 S3 export권한입니다.
GRANT AWS_LOAD_S3_ACCESS TO 'user'@'domain-or-ip-address'
GRANT AWS_SELECT_S3_ACCESS TO 'user'@'domain-or-ip-address'
Mysql Aurora 실습 데이터 준비
Mysql Aurora import/export 데이터는 TPC-H를 사용했습니다.
- TPC-H 정리: https://malwareanalysis.tistory.com/878
lineitem table을 사용했고 row개수는 약 1800만건입니다. dbgen명령어로 약 1800만건 row를 생성했습니다.
git clone https://github.com/electrum/tpch-dbgen
cd tpch-dbgen
time ./dbgen -s 3 -T L


S3 import를 병행으로 실행하기 위해 약 1800만건 데이터를 여러 파일로 분리했습니다.
split -l 700000 lineitem.tbl lineitem_


분리한 데이터는 s3에 업로드했습니다.

데이터베이스에서는 tpch database를 만들고 테이블을 만들었습니다. 테이블 생성 sql는 tpch-dbgen github repo에 있습니다.
mysql -h $HOST -u$USER -p$PASSWORD << EOF
CREATE DATABASE tpch;
USE tpch;
SOURCE dss.ddl;
EOF
Mysql Aurora Import sql
LOAD DATA FROM S3 PREFIX sql로 s3 데이터를 import합니다.
BUCKET="s3://akubun-9umx9v5r/import/lineitem_"
time mysql -h $HOST -u$USER -p$PASSWORD tpch << EOF
LOAD DATA FROM S3 PREFIX '$BUCKET'
INTO TABLE LINEITEM
FIELDS TERMINATED BY '|'
LINES TERMINATED BY '\n';
EOF

저는 S3버킷에서 lineitem_으로 시작하는 버킷 item을 했습니다.

db.t4g.medium 스펙기준으로 1800만건 s3 import작업은 약 7분이 걸렸습니다.

데이터가 잘 들어갔는지 확인합니다. 저는 COUNT문을 사용했습니다.
mysql -h $HOST -u$USER -p$PASSWORD tpch << EOF
SELECT COUNT(*) FROM LINEITEM
EOF

Mysql Aurora export sql
S3 export는 INTO OUTFILE S3 sql로 실행합니다. 버킷경로는 prefix를 지정합니다.
BUCKET="s3://akubun-9umx9v5r/export/mysql_export"
time mysql -h $HOST -u$USER -p$PASSWORD tpch << EOF
SELECT * FROM LINEITEM
LIMIT 10
INTO OUTFILE S3 '${BUCKET}'
FIELDS TERMINATED BY '|'
LINES TERMINATED BY '\n'
MANIFEST ON
OVERWRITE ON;
EOF
export된 데이터는 파티션 단위(part_xxxx)로 저장됩니다.


manifest는 export한 데이터의 정보를 저장합니다.

manifest는 S3 import할때 사용할 수 있습니다.
LOAD DATA FROM S3 MANIFEST ...
Postgres Aurora 설정
1. RDS에 IAM role 연결
RDS 대시보드에서 Connectivity & security → Managed IAM roles에서 IAM role을 attach합니다. s3 import에 사용할 IAM role과 s3 export사용할 IAM role을 각각 만들어야 합니다.

IAM role의 policy는 아래처럼 설정합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::akubun-9umx9v5r"
},
{
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:PutObject",
"s3:DeleteObject",
"s3:AbortMultipartUpload",
"s3:ListMultipartUploadParts"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::akubun-9umx9v5r/*"
}
]
}

IAM role은 RDS가 assume할 수 있도록 Trust relationship을 설정합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AssumeRoleForBackup",
"Effect": "Allow",
"Principal": {
"Service": "rds.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
2. aws_s3 extension 설치
postgres aurora에서 s3 import/export를 사용하기 위해서, aws_s3 extension을 설치해야 합니다.
postgres extension은 database가 필요하기 때문에, database를 먼저 생성합니다.
USER=testuser
psql -h $HOST -U $ROOT_USER -d $DATABASE << EOF
CREATE USER $USER;
GRANT $USER TO $USERROOT_USER;
CREATE DATABASE tpch OWNER $USER;
EOF

방금 생성한 tpch database에 aws s3 extension을 설치합니다. “\dx” sql는 현재 database에 설치된 extension목록을 조회합니다. “\dx” sql실행결과에서 aws_s3 extension이 있어야합니다.
psql -h $HOST -U $ROOT_USER -d tpch << EOF
CREATE EXTENSION aws_s3 CASCADE;
\dx
EOF

Postgres Aurora 실습 데이터 준비
Postgres Aurora import/export 데이터는 TPC-H를 사용했습니다.
- TPC-H 정리: https://malwareanalysis.tistory.com/878
tpch-dbgen을 git clone합니다.
git clone https://github.com/electrum/tpch-dbgen
cd tpch-dbgen
postgres는 import할 때 데이터 마지막에 구분자가 없어야 합니다. 마지막에 구분자가 있다면 아래 에러를 마주칩니다.
ERROR: extra data after last expected column


따라서 데이터를 생성하는 dbgen에서 마지막 구분자를 생성하지 못하도록 컴파일 옵션을 수정해야 합니다. CFLAGS에 -DEOL_HANDLING를 추가합니다. 그리고 make로 컴파일하여 dbgen 바이너리를 생성합니다.
$ vi makefile
CFLAGS = -g -DDBNAME=\"dss\" -D_FILE_OFFSET_BITS=64 -DEOL_HANDLING
$ make
lineitem table을 사용했고 row개수는 약 600만건입니다. dbgen명령어로 약 600만건 row를 생성했습니다.
time ./dbgen -s 1 -T
생성된 lineitem.tbl파일 끝에 구분자가 없는지 확인합니다.

분리한 데이터는 s3에 업로드했습니다. 업로드할 때 확장자를 tbl에서 csv로 변경합니다.
mv lineitem.tbl lineitem.csv

postgres에서는 tpch database를 만들고 테이블을 만들었습니다. postgres는 mysql하고 다르게 database를 만들때 role을 설정해야됩니다.
psql -h $HOST -U $ROOT_USER -d $DATABASE << EOF
CREATE USER $USER;
GRANT $USER TO $USERROOT_USER;
CREATE DATABASE tpch OWNER $USER;
EOF
table 생성 sql은 dss.ddl를 그대로 사용했습니다. 테이블 생성 sql는 tpch-dbgen github repo에 있습니다.
psql -h $HOST -U $ROOT_USER -d tpch -f dss.ddl

Postgres Aurora S3 import sql
postgres는 aws_s3 create_s3_uri의 table_import_from_s3함수를 사용해서 s3 import를 합니다.
- 버킷 위치: s3://akubun-9umx9v5r/import/lineitem.csv
time psql -h $HOST -U $ROOT_USER -d tpch << EOF
SELECT aws_s3.table_import_from_s3(
'LINEITEM',
'',
'(format text, delimiter ''|'')',
aws_commons.create_s3_uri(
'akubun-9umx9v5r',
'import/lineitem.csv',
'ap-northeast-2'
)
);
EOF

Postgres Aurora S3 export sql
postgres s3 export는 aws_s3 extension의 query_export_to_s3함수를 사용합니다.
psql -h $HOST -U $ROOT_USER -d tpch << EOF
SELECT * FROM aws_s3.query_export_to_s3(
'SELECT * FROM LINEITEM LIMIT 10',
aws_commons.create_s3_uri(
'akubun-9umx9v5r',
'export/postgres/lineitem_sample.csv',
'ap-northeast-2'
),
options := 'format csv, delimiter ''|'', header true'
);
EOF

s3에 postgres가 생성한 csv파일이 보입니다.

csv파일을 다운로드해서 보면 의도한대로 파일이 잘 추출되었습니다.

'전공영역 공부 기록' 카테고리의 다른 글
| 크기가 큰 csv파일을 리눅스 명령어로 여러 파일로 분할시키는 방법 (0) | 2025.11.09 |
|---|---|
| 데이터베이스 성능 벤치마크할때 사용하기 좋은 TPC-H (0) | 2025.11.08 |
| 테라폼으로 내 PC IP를 security group에 설정하는 방법 (0) | 2025.11.08 |
| AWS Auto Scaling Group 배포 전략 (0) | 2025.10.12 |
| Argo CD v3.2 업데이트 내용: Application path에서 "." 또는 ""(공백)을 더 이상 사용할 수 없습니다. (0) | 2025.10.09 |