[Django] bulk_create로 한번에 저장하기

김재연·2022년 4월 1일
1

bulk_create란?

한 번의 요청으로 테이블에 대량의 레코드를 삽입하고 싶을 때, 아래처럼 for문을 이용할 수 있다.

users = User.objects.all()
for user in users:
    Notification(user=user, contents="반갑습니다.").save()

근데 이러면 save()를 부를 때마다 DB와 커넥션이 발생해서 서비스에 큰 부하를 일으킬 수 있다. 이때 쓰는 것이 bulk_operation으로, 한 번의 커넥션만으로 다수의 레코드를 생성하고 업데이트할 수 있다. 사용법은 만들고자 하는 테이블 모델의 오브젝트 리스트를 만들어서 bulk_create의 인자로 넘겨주면 된다.

users = User.objects.all()
new_noti_list = [Notification(user=user, contents="반갑습니다.") for user in users]
Notification.objects.bulk_create(new_noti_list)

for문으로 오브젝트들을 하나씩 건드리는건 똑같지만 디비에는 한번의 커넥션만으로 삽입이 가능하다는 점에서 다르다.


수정한 코드

  • 기존코드
image_strings = self.context.get("images")
        decoded = []
        for image_string in image_strings:
            decoded.append(base64.b64decode(image_string))

        num = 1
        for img in decoded:
            filename = f'{img}'
            media_root = settings.MEDIA_ROOT + '\\' + "filename"+str(num)+".png"
            with open(media_root, 'wb') as f:
                f.write(img)
                ProductImg.objects.create(
                    image = f'/filename{num}.png',
                    product=product
                )
            num += 1
  • 현재코드
bulk_list = []
        num = 1
        for image_string in self.context.get("images"):
            image_data = base64.b64decode(image_string)  # 이미지 디코딩
            image_root = settings.MEDIA_ROOT + '\\' + str(num) + ".png" # 이미지 파일 경로
            with open(image_root, 'wb') as f:
                f.write(image_data) # 이미지 파일 생성
                bulk_list.append(ProductImg(product=product, image=f'{num}.png'))
            num += 1

        images = ProductImg.objects.bulk_create(bulk_list)

기존코드에서는 디코딩하느라 for문 한번 돌고, 이미지 파일 만들어서 디비에 저장하느라 for문 한번 돌고, 또 두번째 for문에서는 매번 objects.create()를 통해 디비에 접근해서 이미지 객체를 등록했다. bulk_create() 를 사용해서 바꾼 현재 코드에서는 일단 for문을 한번밖에 돌지 않는다. 불필요한 부분은 다 빼고 한큐에 해결하는 쪽으로 코드를 수정했다. for문을 한번 돌면서 디코딩한 값을 image_data에 저장하고, image_root에 그 이미지 파일 경로를 넣은 다음, 그 파일을 열어서 image_data를 그대로 써주고 bulk_listProductImg 객체를 추가한다. 이때 create를 사용하지는 않았기 때문에 아직 디비에는 한번도 접근하지 않은 것이다. 이제 반복문을 나와서 bulk_create를 통해 bulk_list에 있는 이미지 객체들을 한방에 디비에 등록해준다.

테스트 결과 bulk_create 로도 다음과 같이 디비에 잘 저장이 됐다.

profile
일기장같은 공부기록📝

0개의 댓글