본문 바로가기

Python/Django

Django - Bulk_create 로 대량의 데이터 DB에 insert하기

대량의 데이터라고 하지만, 내 경우엔 겨우 300개의 데이터ㅎㅎ

다만, 다수의 DB Connection을 맺는 것 보다 한번에 삽입하는게 더 효율적으로 생각되어 bulk_create를 사용해서 insert 하기로 했다. 

 

bulk_create()

bulk_create(objsbatch_size=Noneignore_conflicts=False

>>> objs = Entry.objects.bulk_create([
...     Entry(headline='This is a test'),
...     Entry(headline='This is only a test'),
... ])

한번의 쿼리로 다수의 생성된 개체를 db내 삽입 한다.

objs 에 모델명(필드명1 = 밸류, 필드명2=밸류)를 요소로 하는 list를 사용한다. 

 

두 개로 분리시 list 내 아래와 같이 삽입하여 사용 가능하다. 

batch = [] 				#list 선언 
for i in range(1000):
	batch.append(Entry(headline='Test %s' % i))    
    
Entry.objects.bulk_create(batch)

 

공식 가이드 코드로는 (하단 5번 참고) 

from itertools import islice # 반복가능 객체에서 자르고 싶은 만큼 자를 수 있음 

batch_size = 100
objs = (Entry(headline='Test %s' % i) for i in range(1000))
while True:
    batch = list(islice(objs, batch_size))
    if not batch:
        break
    Entry.objects.bulk_create(batch, batch_size)

 

 

JSON 데이터 파싱 후 bulk_create 건 : 

    data = json.loads(response.text)

    datafileBulk = []
    for value in data:
        print('value : {}'.format(value))
        eno = None
        if type(value['ENo']) is str :
            eno = None
        else :
            eno = value['EmailNo']
        datafileBulk.append(
            datafile(
                name = value['Name'],
                emailno = value['EmailNo'],
                email = value['Email'],
            )
        )

    datafile.objects.bulk_create(datafileBulk)

 

 

주의사항

1. Model의 save()메소드가 호출되지 않으며 pre_save 와 post_save 신호가 전송되지 않음

      - DB에 직접 저장하는 방식이기 때문에 Model에서 제공하는 기본 메소드의 지원을 받을 수 없다. 

        데이터 무결성이 깨질 수 있기 때문에 데이터 삽입 전, 모든 필드에 유효한 값이 있는지 확인해야 한다. 

 

2. 다중 테이블 상속 시나리오의 하위모델에서 수행 불가 

 

3. 만약 Model의 기본키가 AutoField인 경우 PostgreSQL 과 MariaDB 10.5 이상에서만 셋팅 됨 

   - 다른 데이터베이스에서는 설정되지 않음 

   - PK 를 지정하지 않을 경우 마지막 생성 PK 다음 번호부터 생성 됨 

 

4. many-to-many 관계에서는 작동하지 않음 

 

5. It casts objs to a list, which fully evaluates objs if it’s a generator.

    The cast allows inspecting all objects so that any objects with a manually set primary key can be inserted first.

    If you want to insert objects in batches without evaluating the entire generator at once,

    you can use this technique as long as the objects don’t have any manually set primary keys: 

 

6. batch_size 파라미터는 단일 쿼리에 생성되는 개체수를 제어.

    SQLite는 쿼리당 999개의 변수가 사용되나 그외 DB는 모든 개체를 한번에 생성 가능 

 

7. ignore_conflicts = True 셋팅 시

  - Oracle을 제외한 모든 DB에서 모든 unique 값과 constraints 실패시 무시하라는 메세지 표기(tells) 

  - 활성화 시 DB에서 지원하는 경우 각 모델 instance에서 기본키 셋팅 불가

    (Enabling this parameter disables setting the primary key on each model instance)

   - MySQL 및 MariaDB에서 셋팅 시  duplicate key키에 대한 오류가 경고로 변경됨 (Strict Mode에서도 동일)

 

8. bulk_create 일부라도 실패시 전체 롤백 됨 - DB에 INSERT 되지 않음 

 

 

 

 

 참고 사이트 :

'Python > Django' 카테고리의 다른 글

Django - Truncate 수행 & Django내 스크립트 실행  (0) 2022.10.25
Django ORM과 QuerySet  (0) 2022.10.22
Django Model - Field 들 소개  (0) 2022.10.07
Django Form 작성 방법  (0) 2022.10.03
우분투 내 MariaDB 설치  (0) 2022.09.28