Browse Source

Fixed #30828 -- Added how to remove/insert many-to-many relations in bulk to the database optimization docs.

David Foster 5 years ago
parent
commit
6a04e69e68
2 changed files with 63 additions and 0 deletions
  1. 1 0
      AUTHORS
  2. 62 0
      docs/topics/db/optimization.txt

+ 1 - 0
AUTHORS

@@ -231,6 +231,7 @@ answer newbie questions, and generally made Django that much better:
     David Cramer <dcramer@gmail.com>
     David Danier <david.danier@team23.de>
     David Eklund
+    David Foster <david@dafoster.net>
     David Gouldin <dgouldin@gmail.com>
     david@kazserve.org
     David Krauth

+ 62 - 0
docs/topics/db/optimization.txt

@@ -410,3 +410,65 @@ objects to reduce the number of SQL queries. For example::
     my_band.members.add(my_friend)
 
 ...where ``Bands`` and ``Artists`` have a many-to-many relationship.
+
+When inserting different pairs of objects into
+:class:`~django.db.models.ManyToManyField` or when the custom
+:attr:`~django.db.models.ManyToManyField.through` table is defined, use
+:meth:`~django.db.models.query.QuerySet.bulk_create()` method to reduce the
+number of SQL queries. For example::
+
+    PizzaToppingRelationship = Pizza.toppings.through
+    PizzaToppingRelationship.objects.bulk_create([
+        PizzaToppingRelationship(pizza=my_pizza, topping=pepperoni),
+        PizzaToppingRelationship(pizza=your_pizza, topping=pepperoni),
+        PizzaToppingRelationship(pizza=your_pizza, topping=mushroom),
+    ], ignore_conflicts=True)
+
+...is preferable to::
+
+    my_pizza.toppings.add(pepperoni)
+    your_pizza.toppings.add(pepperoni, mushroom)
+
+...where ``Pizza`` and ``Topping`` have a many-to-many relationship. Note that
+there are a number of :meth:`caveats to this method
+<django.db.models.query.QuerySet.bulk_create>`, so make sure it's appropriate
+for your use case.
+
+Remove in bulk
+--------------
+
+When removing objects from :class:`ManyToManyFields
+<django.db.models.ManyToManyField>`, use
+:meth:`~django.db.models.fields.related.RelatedManager.remove` with multiple
+objects to reduce the number of SQL queries. For example::
+
+    my_band.members.remove(me, my_friend)
+
+...is preferable to::
+
+    my_band.members.remove(me)
+    my_band.members.remove(my_friend)
+
+...where ``Bands`` and ``Artists`` have a many-to-many relationship.
+
+When removing different pairs of objects from :class:`ManyToManyFields
+<django.db.models.ManyToManyField>`, use
+:meth:`~django.db.models.query.QuerySet.delete` on a
+:class:`~django.db.models.Q` expression with multiple
+:attr:`~django.db.models.ManyToManyField.through`  model instances to reduce
+the number of SQL queries. For example::
+
+    from django.db.models import Q
+    PizzaToppingRelationship = Pizza.toppings.through
+    PizzaToppingRelationship.objects.filter(
+        Q(pizza=my_pizza, topping=pepperoni) |
+        Q(pizza=your_pizza, topping=pepperoni) |
+        Q(pizza=your_pizza, topping=mushroom)
+    ).delete()
+
+...is preferable to::
+
+    my_pizza.toppings.remove(pepperoni)
+    your_pizza.toppings.remove(pepperoni, mushroom)
+
+...where ``Pizza`` and ``Topping`` have a many-to-many relationship.