상상해봐, 너가 백만 줄짜리 데이터를 로딩해야 해. 이걸 느리게 하면 서버가 한참 바쁘고, 사용자들은 DB가 느려져서 짜증날 수도 있고, 더 최악은 네 커피가 다 식을 수도 있어. 최적화를 하면 서버 과부하도 막고, 기다리는 시간도 줄이고, 로딩 중에 에러 날 확률도 최소화할 수 있어.
일단 쉬운 것부터 시작해서, 점점 더 고급지고 꿀팁스러운 방법으로 넘어가자.
인덱스랑 트리거 끄기
인덱스랑 트리거는 DB를 똑똑하고 반응 빠르게 만들어주는 멋진 기능이야. 근데 대량 데이터 로딩할 때는 얘네가 오히려 느려지게 만들어. 왜냐면 서버가 네가 넣는 각 줄마다 인덱스 갱신하고 트리거 실행하려고 하거든.
이 부담을 잠깐 없애려면, 그냥 꺼버리면 돼.
인덱스랑 트리거 끄는 예시:
-- students 테이블의 트리거 끄기
ALTER TABLE students DISABLE TRIGGER ALL;
-- 데이터 로딩
COPY students FROM '/path/to/students.csv' DELIMITER ',' CSV HEADER;
-- 트리거 다시 켜기
ALTER TABLE students ENABLE TRIGGER ALL;
이게 어떻게 동작하냐면?
DISABLE TRIGGER ALL명령어로 모든 트리거를 잠깐 꺼.- 데이터 다 넣고 나서
ENABLE TRIGGER ALL로 다시 켜.
자주 하는 실수: 트리거 다시 켜는 걸 까먹으면, 자동화 프로세스(예: 기본값 필드 업데이트 같은 거)가 제대로 안 돌아갈 수 있어. 그러니까 꼭 다시 켜줘야 해 — 이건 마치 폰에서 "비행기 모드" 풀어주는 거랑 똑같아.
트랜잭션 사용하기
트랜잭션을 쓰면 모든 데이터를 한 번에, 마치 하나의 큰 작업처럼 넣을 수 있어. 만약 뭔가 잘못되면, 변경사항을 다 롤백할 수 있어서 DB가 데이터 조각난 죽이 되는 걸 막아줘.
트랜잭션 예시:
-- 트랜잭션 시작
BEGIN;
-- 데이터 로딩
COPY courses FROM '/path/to/courses.csv' DELIMITER ',' CSV HEADER;
-- 변경사항 확정
COMMIT;
왜 이게 더 빠르냐면?
트랜잭션 없이 데이터 넣으면, 서버가 각 줄마다 변경사항을 확정해. 트랜잭션을 쓰면 마지막에 한 번만 확정해서, 시간 엄청 아낄 수 있어.
무결성 검사 끄기
로딩 중에 외래키나 유니크 제약조건 검사 필요 없으면, 그냥 꺼버려. 안 그러면 DB가 각 줄마다 검사해서 느려져.
무결성 검사 끄는 예시:
SET session_replication_role = 'replica';
-- 데이터 로딩
COPY enrollments FROM '/path/to/enrollments.csv' DELIMITER ',' CSV HEADER;
SET session_replication_role = 'origin';
session_replication_role = 'replica'는 데이터 무결성 검사(예: 유니크, FOREIGN KEY 제약조건 등)를 꺼줘.
실행 메모리 늘리기
PostgreSQL의 메모리 세팅을 잘 하면 데이터 로딩 성능이 확 좋아져. 중요한 파라미터는 work_mem이랑 maintenance_work_mem이야.
메모리 늘리는 예시:
-- 메모리 용량 늘리기
SET work_mem = '64MB';
SET maintenance_work_mem = '256MB';
-- 데이터 로딩
COPY teachers FROM '/path/to/teachers.csv' DELIMITER ',' CSV HEADER;
이게 뭐가 좋냐면?
work_mem은 정렬이나 해시 같은 중간 작업에 쓰여.maintenance_work_mem은 인덱스 재구성 같은 작업에 영향 줘.
팁: 메모리 늘릴 때는 특히 리소스 적은 서버에서는 조심해야 해.
데이터 미리 준비하기
데이터를 미리 준비하면 로딩 시간이 확 줄어. 예를 들어, 중복된 줄이 있으면 미리 필터링해서 PostgreSQL이 쓸데없는 데이터 처리 안 하게 해.
데이터 정리 예시:
중복 줄이 있는 파일이면, Python으로 중복 제거할 수 있어.
import pandas as pd
# CSV 파일 로딩
data = pd.read_csv('students.csv')
# 중복 제거
data = data.drop_duplicates()
# 정리된 CSV 저장
data.to_csv('students_clean.csv', index=False)
데이터 파티셔닝
파일이 엄청 크면, 여러 개의 작은 파일로 쪼개. 그러면 PostgreSQL이 더 효율적으로 처리할 수 있어.
예시:
large_data.csv 파일을 Linux에서 1000줄씩 쪼개기:
split -l 1000 large_data.csv chunk_
그리고 나서 각각 따로 로딩:
COPY students FROM 'chunk_aa' DELIMITER ',' CSV HEADER;
COPY students FROM 'chunk_ab' DELIMITER ',' CSV HEADER;
-- 계속 반복
백그라운드로 로딩하기
가능하면, 데이터 로딩을 백그라운드 프로세스로 돌려서 메인 DB에 부담 안 주는 게 좋아.
pg_cron 같은 툴을 쓰면 스케줄대로 작업을 돌릴 수 있어.
예시: pg_cron으로 백그라운드 로딩 세팅하기:
CREATE EXTENSION pg_cron;
SELECT cron.schedule('*/5 * * * *', $$COPY students FROM '/path/to/data.csv' DELIMITER ',' CSV HEADER$$);
5분마다 파일에서 테이블로 데이터가 들어가.
이건 그냥 예시야, 실제로 이렇게 쓰진 마! PostgreSQL이 진짜 유연하다는 걸 보여주고 싶었어. SQL 스크립트에서 데이터 추가를 엄청 유연하게 할 수 있다는 거지.
주의할 점
몇 가지 꼭 신경 써야 할 것들:
- 인덱스랑 트리거 껐다면, 꼭 다시 켜! 까먹으면 로딩 끝나고 에러 고치느라 고생할 수도 있어.
- 메모리 파라미터 올릴 때는 서버 리소스 잘 봐야 해: 한 번에 너무 많이 쓰면 램 다 써버릴 수도 있어.
- 트랜잭션 쓸 때는 데이터 파일에 치명적인 에러가 없는지 꼭 확인해. 한 줄만 에러 나도 전체 로딩이 롤백돼.
앞으로의 추천
이제 대량 데이터 로딩을 최적화하는 방법 — 인덱스 끄기부터 트랜잭션까지 — 다 알았지! 이 스킬로 데이터 더 빨리 넣고, 서버 리소스랑 너의 멘탈, 커피까지 아끼고, 사용자들도 만족시킬 수 있어.
다음에 기가바이트급 파일 작업할 일 있으면, 이제 준비됐지!
GO TO FULL VERSION