MySQL에서 데이터를 삽입하는 INSERT 문은 기본 중의 기본이지만,
수천, 수만 건의 대량 데이터를 INSERT할 경우,
성능 저하와 디스크 부하, 트랜잭션 병목 등 다양한 이슈가 발생할 수 있다.
🔍 기본 INSERT는 어떻게 동작할까?
MySQL에서 INSERT는 한 번에 한 건씩 처리하면 다음과 같은 쿼리가 된다.
INSERT INTO members (name, age) VALUES ('홍길동', 25);
INSERT INTO members (name, age) VALUES ('김철수', 31);
INSERT INTO members (name, age) VALUES ('이영희', 22);
위 방식은 SQL 파싱, 실행, 인덱스 처리, 디스크 쓰기가 반복적으로 일어나기 때문에 성능이 매우 떨어질 수 있다.
✅ 1. 다중 행 INSERT로 병합하기
가장 기본적인 최적화 방법은 한 번에 여러 행을 삽입하는 것이다.
INSERT INTO members (name, age) VALUES
('홍길동', 25),
('김철수', 31),
('이영희', 22),
('최민수', 28);
이렇게 하면 SQL 파싱 및 디스크 쓰기 비용이 절반 이하로 줄어든다.
MySQL은 내부적으로 이를 한 트랜잭션으로 처리하므로 훨씬 빠르게 작동한다.
💡 Tip: 한 번에 삽입하는 행 수는 100~1,000개 정도가 권장됨
✅ 2. 트랜잭션 사용으로 COMMIT 최적화
기본적으로 MySQL은 autocommit 모드가 켜져 있어서
각 INSERT마다 자동 커밋을 수행한다.
이 방식은 성능에 큰 병목이 된다.
SET autocommit = 0;
START TRANSACTION;
INSERT INTO ...
INSERT INTO ...
...
COMMIT;
이렇게 여러 INSERT를 한 번의 트랜잭션으로 묶으면
디스크 커밋 횟수가 줄어들어 속도가 대폭 향상된다.
✅ 3. 인덱스 최소화 또는 작업 후 생성
데이터를 많이 넣는 테이블이라면
초기에는 인덱스를 제거한 상태로 INSERT하고,
모든 데이터를 넣은 후 인덱스를 다시 생성하는 전략이 유효하다.
-- 인덱스 제거
ALTER TABLE members DROP INDEX idx_name;
-- 대량 INSERT 수행
-- 인덱스 복구
ALTER TABLE members ADD INDEX idx_name(name);
인덱스가 많을수록 INSERT 속도가 느려지므로
대량 데이터 적재 시에는 인덱스를 최소화하자.
✅ 4. REPLACE 또는 UPSERT 대신 INSERT만 사용하기
REPLACE나 INSERT ... ON DUPLICATE KEY UPDATE 구문은
내부적으로 DELETE → INSERT 또는 INSERT + UPDATE 처리를 수행한다.
이로 인해 성능이 급격히 하락할 수 있다.
대량 데이터를 처리할 때는 충돌 가능성이 없는 순수 INSERT가 가장 빠르다.
✅ 5. LOAD DATA INFILE 사용하기
MySQL에서 대량 데이터를 삽입할 때 가장 빠른 방법은
바로 LOAD DATA INFILE이다.
LOAD DATA INFILE '/var/lib/mysql-files/members.csv'
INTO TABLE members
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;
CSV 파일 형식으로 데이터를 미리 저장해두고,
LOAD DATA INFILE을 사용하면 수백만 건도 단 몇 초 안에 삽입할 수 있다.
💡 Tip: LOCAL 옵션을 사용하면 클라이언트 파일도 불러올 수 있음
✅ 6. 비동기 방식 또는 배치 처리 도입
애플리케이션에서는 실시간으로 모든 데이터를 DB에 넣지 말고,
배치(Batch)나 버퍼링 큐 방식으로 모아서 한 번에 INSERT하는 것이 좋다.
예를 들어 Node.js나 Java에서는 아래와 같이 구현한다.
// Node.js 예시 - 100건 단위로 쌓이면 한 번에 INSERT
const buffer = [];
function insertData(data) {
buffer.push(data);
if (buffer.length >= 100) {
connection.query('INSERT INTO members ...', buffer);
buffer.length = 0;
}
}
이 방식은 DB 부하를 줄이고, 전체 성능을 안정적으로 유지시켜 준다.
✅ 7. INSERT DELAYED (주의: 더 이상 비추천)
과거에는 INSERT DELAYED 명령어도 존재했지만,
MySQL 5.7부터는 더 이상 권장되지 않으며 일부 버전에서는 제거되었다.
사용 금지 또는 대체 전략 권장
🧠 정리하자면…
- INSERT 시 다중 행 병합은 기본 중 기본
- 트랜잭션으로 커밋 횟수 최소화
- 인덱스는 최소화 → 후에 재생성
- UPSERT 대신 순수 INSERT만 사용
- 가능하다면 LOAD DATA INFILE 적극 활용
- 백엔드에서는 비동기, 버퍼, 배치 INSERT로 처리
- 성능 측정을 통해 적절한 삽입량(행 수)을 조정
📎 공식 문서 참고
MySQL INSERT 성능 공식 가이드
https://dev.mysql.com/doc/refman/8.0/en/insert-optimization.html
'DB' 카테고리의 다른 글
[MySQL] REPLACE VS INSERT 차이점 완벽 정리 (0) | 2025.06.20 |
---|---|
[MySQL] INSERT + AUTO_INCREMENT 사용법 완벽 가이드 (0) | 2025.06.20 |
[MySQL] INSERT + 트랜잭션(Transaction) 연동 완벽 가이드 (1) | 2025.06.20 |
[MySQL] INSERT + SELECT 사용법 완벽 가이드 (0) | 2025.06.20 |
[MySQL] 있으면 UPDATE, 없으면 INSERT (오라클의 MERGE INTO) (2) | 2025.06.19 |
[MySQL] INSERT IGNORE 사용법 완벽 가이드(데이터 중복 방지) (0) | 2025.06.19 |
[MySQL] INSERT INTO ... SET 사용법 완벽 가이드 (1) | 2025.06.19 |
[MySQL] INSERT 다중 행 삽입 사용법 완벽 가이드 (1) | 2025.06.19 |