VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
INSERT를 완전한 트랜잭션 커밋으로 처리합니다 — 파싱, 계획, 실행, fsync. 규모가 커지면 행당 오버헤드가 지배적이 됩니다. 이를 피하는 방법은 다음과 같습니다.
다중 행 INSERT
가장 간단한 최적화: 여러 행을 하나의 문으로 묶습니다.트랜잭션 배치 처리
많은 INSERT를 하나의 트랜잭션으로 감싸면 문마다 발생하는 커밋 오버헤드를 피할 수 있습니다:LOAD DATA INFILE
큰 CSV 가져오기에는LOAD DATA INFILE이 가장 빠른 MySQL 네이티브 옵션입니다 — 행마다 SQL 파싱을 거치지 않으므로 배치 INSERT보다 훨씬 빠릅니다.
secure_file_priv로 지정된 디렉토리로 제한됩니다:
LOCAL INFILE은 서버에서 local_infile = ON이 설정되어 있어야 하고, 클라이언트에서 --local-infile 플래그가 활성화되어 있어야 합니다.
INSERT … SELECT
테이블 간 데이터 복사(ETL 패턴, 스테이징 테이블)에는INSERT...SELECT가 행을 애플리케이션으로 읽어 들여 다시 삽입하는 것보다 빠릅니다:
대량 로드 중 인덱스 비활성화
MyISAM 테이블에서는 대량 삽입 중 비고유 인덱스 업데이트를 비활성화하면 속도가 크게 빨라집니다:unique_checks를 비활성화하면 손상된 인덱스가 만들어집니다.
성능 비교
정확한 수치는 행 크기, 인덱스, 하드웨어, 구성에 따라 크게 달라집니다. 각자의 경우를 벤치마크하세요.
자주 묻는 질문
각 INSERT 배치는 얼마나 커야 하나요?
500–1000행에서 시작하여 벤치마크하세요. 더 큰 배치는 커밋당 오버헤드를 줄이지만 메모리 사용량과 트랜잭션 지속 시간(잠금을 더 오래 유지)을 늘립니다. 배치가 실패하면 배치 전체가 롤백됩니다 — 더 작은 배치는 롤백 작업이 적다는 뜻입니다. 대부분의 애플리케이션에서 최적 배치 크기는 500에서 5000행 사이입니다.LOAD DATA INFILE을 ON DUPLICATE KEY UPDATE와 함께 사용할 수 있나요?
LOAD DATA는 중복 처리를 위해 REPLACE 또는 IGNORE를 지원하지만 ON DUPLICATE KEY UPDATE는 지원하지 않습니다. 대량 로드 중 업서트 동작이 필요하다면 스테이징 테이블에 로드한 다음, 스테이징 테이블에서 대상 테이블로 INSERT...SELECT...ON DUPLICATE KEY UPDATE를 사용하세요.
대량 삽입은 트리거를 우회하나요?
아니요. 트리거는LOAD DATA INFILE과 INSERT...SELECT로 로드된 행을 포함하여 영향을 받는 모든 행에 대해 실행됩니다. 트리거가 많은 작업을 수행한다면 대량 로드가 그에 비례하여 느려집니다. 순수한 데이터 마이그레이션에서는 트리거를 일시적으로 비활성화하는 것이 좋을 수 있습니다.
문제 해결
이 로딩 기법들은 MySQL의 드롭인 대체품이자 확장 기능을 갖춘 VillageSQL에서도 변경 없이 동작합니다.
참고
- MySQL의 트랜잭션 — 안전과 속도를 위해 대량 삽입을 트랜잭션으로 배치 처리하기
- MySQL의 스키마 마이그레이션 — 대량 삽입은 데이터 마이그레이션 작업의 일부인 경우가 많습니다
- MySQL의 UPSERT — 로드 중 중복 키 처리하기
- MySQL 여러 행 삽입 — 다중 행 문 자체
- MySQL INSERT SELECT — 쿼리가 반환하는 행 복사하기