Loading docs/topics/db/optimization.txt +35 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,41 @@ Write your own :doc:`custom SQL to retrieve data or populate models </topics/db/sql>`. Use ``django.db.connection.queries`` to find out what Django is writing for you and start from there. Retrieve individual objects using a unique, indexed column ========================================================== There are two reasons to use a column with :attr:`~django.db.models.Field.unique` or :attr:`~django.db.models.Field.db_index` when using :meth:`~django.db.models.query.QuerySet.get` to retrieve individual objects. First, the query will be quicker because of the underlying database index. Also, the query could run much slower if multiple objects match the lookup; having a unique constraint on the column guarantees this will never happen. So using the :ref:`example Weblog models <queryset-model-example>`:: >>> entry = Entry.objects.get(id=10) will be quicker than: >>> entry = Entry.object.get(headline="News Item Title") because ``id`` is indexed by the database and is guaranteed to be unique. Doing the following is potentially quite slow: >>> entry = Entry.objects.get(headline__startswith="News") First of all, `headline` is not indexed, which will make the underlying database fetch slower. Second, the lookup doesn't guarantee that only one object will be returned. If the query matches more than one object, it will retrieve and transfer all of them from the database. This penalty could be substantial if hundreds or thousands of records are returned. The penalty will be compounded if the database lives on a separate server, where network overhead and latency also play a factor. Retrieve everything at once if you know you will need it ======================================================== Loading tests/modeltests/basic/tests.py +35 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ from __future__ import absolute_import, unicode_literals from datetime import datetime from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned from django.db.models.fields import Field, FieldDoesNotExist from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature from django.utils import six Loading Loading @@ -128,6 +128,40 @@ class ModelTest(TestCase): b = Article.objects.get(pk=a.id) self.assertEqual(a, b) # Create a very similar object a = Article( id=None, headline='Area man programs in Python', pub_date=datetime(2005, 7, 28), ) a.save() self.assertEqual(Article.objects.count(), 2) # Django raises an Article.MultipleObjectsReturned exception if the # lookup matches more than one object self.assertRaisesRegexp( MultipleObjectsReturned, "get\(\) returned more than one Article -- it returned 2!", Article.objects.get, headline__startswith='Area', ) self.assertRaisesRegexp( MultipleObjectsReturned, "get\(\) returned more than one Article -- it returned 2!", Article.objects.get, pub_date__year=2005, ) self.assertRaisesRegexp( MultipleObjectsReturned, "get\(\) returned more than one Article -- it returned 2!", Article.objects.get, pub_date__year=2005, pub_date__month=7, ) def test_object_creation(self): # Create an Article. a = Article( Loading Loading
docs/topics/db/optimization.txt +35 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,41 @@ Write your own :doc:`custom SQL to retrieve data or populate models </topics/db/sql>`. Use ``django.db.connection.queries`` to find out what Django is writing for you and start from there. Retrieve individual objects using a unique, indexed column ========================================================== There are two reasons to use a column with :attr:`~django.db.models.Field.unique` or :attr:`~django.db.models.Field.db_index` when using :meth:`~django.db.models.query.QuerySet.get` to retrieve individual objects. First, the query will be quicker because of the underlying database index. Also, the query could run much slower if multiple objects match the lookup; having a unique constraint on the column guarantees this will never happen. So using the :ref:`example Weblog models <queryset-model-example>`:: >>> entry = Entry.objects.get(id=10) will be quicker than: >>> entry = Entry.object.get(headline="News Item Title") because ``id`` is indexed by the database and is guaranteed to be unique. Doing the following is potentially quite slow: >>> entry = Entry.objects.get(headline__startswith="News") First of all, `headline` is not indexed, which will make the underlying database fetch slower. Second, the lookup doesn't guarantee that only one object will be returned. If the query matches more than one object, it will retrieve and transfer all of them from the database. This penalty could be substantial if hundreds or thousands of records are returned. The penalty will be compounded if the database lives on a separate server, where network overhead and latency also play a factor. Retrieve everything at once if you know you will need it ======================================================== Loading
tests/modeltests/basic/tests.py +35 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ from __future__ import absolute_import, unicode_literals from datetime import datetime from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned from django.db.models.fields import Field, FieldDoesNotExist from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature from django.utils import six Loading Loading @@ -128,6 +128,40 @@ class ModelTest(TestCase): b = Article.objects.get(pk=a.id) self.assertEqual(a, b) # Create a very similar object a = Article( id=None, headline='Area man programs in Python', pub_date=datetime(2005, 7, 28), ) a.save() self.assertEqual(Article.objects.count(), 2) # Django raises an Article.MultipleObjectsReturned exception if the # lookup matches more than one object self.assertRaisesRegexp( MultipleObjectsReturned, "get\(\) returned more than one Article -- it returned 2!", Article.objects.get, headline__startswith='Area', ) self.assertRaisesRegexp( MultipleObjectsReturned, "get\(\) returned more than one Article -- it returned 2!", Article.objects.get, pub_date__year=2005, ) self.assertRaisesRegexp( MultipleObjectsReturned, "get\(\) returned more than one Article -- it returned 2!", Article.objects.get, pub_date__year=2005, pub_date__month=7, ) def test_object_creation(self): # Create an Article. a = Article( Loading