mirror of https://github.com/django/django.git
Fixed #15361 - Documented performance considerations for QuerySet.get()
Thanks mmcnickle for the patch.
This commit is contained in:
parent
92fc263a28
commit
feaf9f279a
|
@ -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
|
</topics/db/sql>`. Use ``django.db.connection.queries`` to find out what Django
|
||||||
is writing for you and start from there.
|
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
|
Retrieve everything at once if you know you will need it
|
||||||
========================================================
|
========================================================
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
from datetime import datetime
|
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.db.models.fields import Field, FieldDoesNotExist
|
||||||
from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
|
from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
@ -128,6 +128,40 @@ class ModelTest(TestCase):
|
||||||
b = Article.objects.get(pk=a.id)
|
b = Article.objects.get(pk=a.id)
|
||||||
self.assertEqual(a, b)
|
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):
|
def test_object_creation(self):
|
||||||
# Create an Article.
|
# Create an Article.
|
||||||
a = Article(
|
a = Article(
|
||||||
|
|
Loading…
Reference in New Issue