Skip to content

Instantly share code, notes, and snippets.

@Flexonze
Last active January 19, 2023 21:02
Show Gist options
  • Save Flexonze/2d5ac2def78c54186628fe33e27415f9 to your computer and use it in GitHub Desktop.
Save Flexonze/2d5ac2def78c54186628fe33e27415f9 to your computer and use it in GitHub Desktop.
django-pgbulk vs Django's bulk_create and bulk_update
from myapp.models import MyModel
from django.test import TestCase
import pgbulk
from time import perf_counter
class TestPgBulk(TestCase):
@classmethod
def setUpTestData(cls):
cls.number_of_objects = 25_000
my_models = []
for i in range(cls.number_of_objects):
my_models.append(
MyModel(name="name")
)
cls.my_model = MyModel.objects.bulk_create(my_models)
def setUp(self):
self.assertEqual(MyModel.objects.filter(name="new name").count(), 0)
for obj in self.my_model:
obj.name = "new name"
def test_bulk_update_with_bulk_update(self):
with self.assertNumQueries(1):
start = perf_counter()
MyModel.objects.bulk_update(self.my_model, ["name"])
end = perf_counter()
print(f"Time with bulk_update: {end - start} seconds")
self.assertEqual(MyModel.objects.filter(name="new name").count(), self.number_of_objects)
def test_bulk_update_with_pgbulk(self):
with self.assertNumQueries(1):
start = perf_counter()
pgbulk.update(MyModel, self.my_model, ["name"])
end = perf_counter()
print(f"Time with pgbulk.update: {end - start} seconds")
self.assertEqual(MyModel.objects.filter(name="new name").count(), self.number_of_objects)
def test_upsert_with_pgbulk(self):
self.my_model = self.my_model[:self.number_of_objects // 2]
self.my_model.extend([MyModel(name="new name") for _ in range(self.number_of_objects // 2)])
with self.assertNumQueries(1):
start = perf_counter()
results = pgbulk.upsert(MyModel, self.my_model, ["id"], ["name"], returning=True)
end = perf_counter()
print(f"Time with pgbulk.upsert: {end - start} seconds")
print(f"Created: {len([result.id for result in results.created])}")
print(f"Updated: {len([result.id for result in results.updated])}")
self.assertEqual(MyModel.objects.filter(name="new name").count(), self.number_of_objects)
def test_upsert_as_bulk_create(self):
my_models = []
for i in range(self.number_of_objects):
my_models.append(
MyModel(name="new name")
)
with self.assertNumQueries(1):
start = perf_counter()
results = pgbulk.upsert(MyModel, my_models, ["id"], ["name"], returning=True)
end = perf_counter()
print(f"Time with pgbulk.upsert as bulk_create: {end - start} seconds")
print(f"Created: {len([result.id for result in results.created])}")
print(f"Updated: {len([result.id for result in results.updated])}")
self.assertEqual(MyModel.objects.filter(name="new name").count(), self.number_of_objects)
def test_upsert_as_bulk_update(self):
with self.assertNumQueries(1):
start = perf_counter()
results = pgbulk.upsert(MyModel, self.my_model, ["id"], ["name"], returning=True)
end = perf_counter()
print(f"Time with pgbulk.upsert as bulk_update: {end - start} seconds")
print(f"Created: {len([result.id for result in results.created])}")
print(f"Updated: {len([result.id for result in results.updated])}")
self.assertEqual(MyModel.objects.filter(name="new name").count(), self.number_of_objects)
def test_django_bulk_create(self):
my_models = []
for i in range(self.number_of_objects):
my_models.append(
MyModel(name="new name")
)
with self.assertNumQueries(1):
start = perf_counter()
self.my_model = MyModel.objects.bulk_create(my_models)
end = perf_counter()
print(f"Time with django_bulk_create: {end - start} seconds")
self.assertEqual(MyModel.objects.filter(name="new name").count(), self.number_of_objects)
@Flexonze
Copy link
Author

Example output:

Time with bulk_update: 21.68879701300102 seconds

Time with pgbulk.update: 0.6510931049997453 seconds

Time with django_bulk_create: 1.6016744959997595 seconds

Time with pgbulk.upsert as bulk_create: 1.7720716830008314 seconds
Created: 25000
Updated: 0

Time with pgbulk.upsert as bulk_update: 2.0506603350004298 seconds
Created: 0
Updated: 25000

Time with pgbulk.upsert: 1.9862078459991608 seconds
Created: 12500
Updated: 12500

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment