Notice
Recent Posts
Recent Comments
Link
오늘도 개발
update와 bulk_update 본문
Writer 인스턴스의 id가 2, 4, 6, 8, 10인 것만 policy=True로 설정된 상태.
policy 필드가 True인 인스턴스의 policy_second 필드도 True로 업데이트하는 상황 가정.
1. iteration과 save 사용
업데이트 대상이 100개라면 UPDATE문이 100번 실행됨.
실행 속도가 느리고, 첫줄에서부터 save()를 실행할 때 까지 데이터에 변경이 일어날 수 있다는 것이 단점.
수많은 row에 한꺼번에 락을 걸지 않는다는 것이 장점.
writers = Writer.objects.filter(policy=True)
for writer in writers:
writer.policy_second = True
writer.save()
SELECT "writers"."id", "writers"."description", "writers"."policy", "writers"."policy_second" FROM "writers" WHERE "writers"."policy"; args=(); alias=default
UPDATE "writers" SET "description" = 'abc', "policy" = 1, "policy_second" = 1 WHERE "writers"."id" = 2; args=('abc', True, True, 2); alias=default
UPDATE "writers" SET "description" = 'abc', "policy" = 1, "policy_second" = 1 WHERE "writers"."id" = 4; args=('abc', True, True, 4); alias=default
UPDATE "writers" SET "description" = 'abc', "policy" = 1, "policy_second" = 1 WHERE "writers"."id" = 6; args=('abc', True, True, 6); alias=default
UPDATE "writers" SET "description" = 'abc', "policy" = 1, "policy_second" = 1 WHERE "writers"."id" = 8; args=('abc', True, True, 8); alias=default
UPDATE "writers" SET "description" = 'abc', "policy" = 1, "policy_second" = 1 WHERE "writers"."id" = 10; args=('abc', True, True, 10); alias=default
2. update 사용
UPDATE.. WHERE..문이 한 번만 실행됨.
WHERE로 잡힌 업데이트 대상이 100개라면 100개에 락이 걸림.
실행 속도가 빠르고 실행 중 데이터가 변경될 염려 없음.
업데이트 대상이 되는 row의 개수가 적을 때만 추천.
Writer.objects.filter(policy=True).update(policy_second=True)
UPDATE "writers" SET "policy_second" = 1 WHERE "writers"."policy"; args=(True,); alias=default
3. bulk_update 사용
1, 2번 절충 가능.
batch_size로 한 번에 업데이트할 row의 개수 지정할 수 있다.
업데이트 대상이 100개이고 batch_size를 20으로 지정하면
- 20개 row에 락을 걸고
- UPDATE를 실행하고
- 락 해제
과정을 5번 반복한다.
(Queryset.update()에는 트랜잭션이 적용된다.)
writers = Writer.objects.filter(policy=True)
writers_to_update = []
for writer in writers:
writer.policy_second = True
writers_to_update.append(writer)
Writer.objects.bulk_update(writers, ['policy_second'], batch_size=2)
# writer 인스턴스를 2개씩 끊어 업데이트
for writer in writers 시 호출
SELECT "writers"."id", "writers"."description", "writers"."policy", "writers"."policy_second" FROM "writers" WHERE "writers"."policy"; args=(); alias=default
Writer.objects.bulk_update(writers_to_update, ['policy_second'], batch_size=2) 시 호출
(0.000) BEGIN; args=None; alias=default
(0.000) UPDATE "writers" SET "policy_second" = CASE WHEN ("writers"."id" = 2) THEN 1 WHEN ("writers"."id" = 4) THEN 1 ELSE NULL END WHERE "writers"."id" IN (2, 4); args=(2, True, 4, True, 2, 4); alias=default
(0.000) UPDATE "writers" SET "policy_second" = CASE WHEN ("writers"."id" = 6) THEN 1 WHEN ("writers"."id" = 8) THEN 1 ELSE NULL END WHERE "writers"."id" IN (6, 8); args=(6, True, 8, True, 6, 8); alias=default
(0.000) UPDATE "writers" SET "policy_second" = CASE WHEN ("writers"."id" = 10) THEN 1 ELSE NULL END WHERE "writers"."id" IN (10); args=(10, True, 10); alias=default
'웹 프로그래밍 > Django' 카테고리의 다른 글
| 모델 필드 추가 시 default 값 설정 (0) | 2023.02.18 |
|---|---|
| 장고가 이미 반영한 마이그레이션을 가려내는 방법 (0) | 2023.02.18 |
| 한 모델에 있는 모든 필드 확인하기 (0) | 2023.02.18 |
| refresh_from_db() (0) | 2023.02.18 |
| django에 데이터베이스 여러 개 연결하기 (0) | 2023.02.18 |