bulk_create와 bulk_update로 대량 데이터 효율적으로 처리하기
Django ORM의 bulk_create와 bulk_update를 사용하여 대량 데이터 처리 시 발생하는 성능 문제를 해결하고, 단일 쿼리로 효율적인 데이터베이스 연산을 수행하는 방법
bulk 연산이 필요한 이유
일반적인 for 루프와 save() 방식은 각 객체마다 별도의 INSERT 쿼리를 생성하여 데이터베이스와 통신. 10,000개 데이터 처리 시 10,000번의 데이터베이스 왕복 발생으로 심각한 성능 저하 야기
bulk 연산은 여러 객체를 단 하나의 SQL 쿼리로 묶어서 처리하여 데이터베이스 통신 횟수를 획기적으로 감소
bulk_create() 사용법
여러 개의 객체를 데이터베이스에 한 번의 쿼리로 삽입하는 메서드
# 효율적인 방식
products_to_create = [
Product(name=f"상품 {i}", price=i * 100) for i in range(10000)
]
Product.objects.bulk_create(products_to_create)주요 파라미터
batch_size: 한 번의 쿼리에 포함할 객체 수 지정. 메모리 부족 방지와 데이터베이스 제한 회피
ignore_conflicts: UNIQUE 제약 조건 위반 시 해당 데이터 무시하고 삽입 계속 (PostgreSQL, SQLite 지원)
주의사항
save() 메서드 미호출: 모델의 커스텀 save() 로직이 실행되지 않음
시그널 미발생: pre_save, post_save 시그널이 트리거되지 않음
PK 자동 할당: MySQL/MariaDB나 구버전 Django에서는 생성된 객체의 PK가 자동으로 채워지지 않음
bulk_update() 사용법
여러 객체의 특정 필드를 한 번의 쿼리로 업데이트하는 메서드
# 업데이트할 객체 조회 및 수정
products_to_update = list(Product.objects.filter(category="전자제품"))
for product in products_to_update:
product.price *= 1.1
# bulk_update로 한 번에 업데이트
Product.objects.bulk_update(products_to_update, fields=['price'])주요 파라미터
fields: 업데이트할 필드명 리스트 (필수)
batch_size: 대량 객체 처리 시 적절한 크기로 분할
주의사항
save() 메서드와 시그널 미호출: bulk_create와 동일한 제약
PK 필수: 업데이트 대상 객체는 반드시 PK를 보유해야 함
관계 필드 제한: ForeignKey는 필드명이 아닌 실제 컬럼명(예: category_id) 사용 필요
활용 시나리오
초기 데이터 세팅: 테스트나 프로덕션 환경의 기본 데이터 대량 입력
CSV/Excel 파일 처리: 대용량 파일 데이터의 일괄 업로드 및 저장
데이터 마이그레이션: 기존 데이터의 새로운 스키마 이전
주기적 데이터 동기화: 외부 API 데이터의 정기적 반영
Last updated
