Loop instance.save() cho 10k row = 10k INSERT round-trip → tốn vài chục giây và ép DB ngộp connection. Bulk operations gom thành 1-N câu SQL, nhanh hơn 10–100 lần.
Model.objects.bulk_create(objs, batch_size=1000) chạy 1 INSERT cho mỗi batch, có ignore_conflicts=True (skip duplicate) và update_conflicts=True (upsert kiểu Postgres). Model.objects.bulk_update(objs, fields, batch_size=1000) chạy 1 UPDATE ... CASE WHEN cho mỗi batch — object phải có sẵn pk. QuerySet.update(**kwargs) chạy 1 UPDATE SQL cho mọi row match filter, không cần load object về Python.
# Sai: 10k query
for row in rows:
Item(sku=row.sku, price=row.price).save()
# Đúng: 10 query (batch_size=1000)
Item.objects.bulk_create(
[Item(sku=r.sku, price=r.price) for r in rows],
batch_size=1000,
)
# Cập nhật cùng giá trị, không cần load object
Item.objects.filter(category='archived').update(visible=False)Bulk operation bỏ qua signal và bỏ qua Model.save() override — nếu logic phụ thuộc signal (audit log, invalidate cache) thì phải tự handle sau bulk. auto_now cũng không chạy với update(); truyền updated_at=timezone.now() thẳng vào kwargs khi cần.