#30079: Prefetch cache should be aware of database source and .using() should
not
always trigger a new query
-------------------------------------+-------------------------------------
Reporter: Mike | Owner: nobody
Lissner |
Type: Bug | Status: new
Component: Database | Version: 2.1
layer (models, ORM) | Keywords: prefetch,
Severity: Normal | multidatabase
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
I've been poking around the darker edges of multidatabase prefetching and
I discovered a strange pattern. When you have cached prefetch values,
they're not aware of which database they came from:
{{{
# This runs zero queries
In [62]: pizzas =
Pizza.objects.filter(pk=17).prefetch_related('toppings').using('replica')
# This runs two, as expected
In [63]: pizza0 = pizzas[0]
# This runs zero, even though it normally would come from "default" and
the cache came from "replica"
In [64]: pizza0.toppings.all()
Out[64]: [<Topping 1: Cheese>, <Topping 2: Bacon>]
# This runs one query, even though this data should already be populated.
In [65]: pizza0.toppings.all().using('replica')
Out[65]: [<Topping 1: Cheese>, <Topping 2: Bacon>]
}}}
I was pretty surprised and confused that adding the using() method on the
last line above busted the cache even when the database selected was the
same as the one used to pre-populate the cache.
I was also surprised (though less so) at the opposite, that *not*
including the non-default DB (on line 64) *was* able to hit the cache
(which was populated by "replica") instead of hitting the default database
(as the query would normally do).
On IRC chatting about this, the question was: "Well, should filter hit the
DB or use the cache? What about exclude and other methods? Where do you
draw the line?" I think the simple line to draw is whether something
changes the SQL query. using() methods don't change SQL, so they should
work properly on a cached result. filter() and exclude() do change the
SQL, so they *shouldn't* use the cache.
--
Ticket URL: <https://code.djangoproject.com/ticket/30079>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/051.56ad9d27482adcbf7542976b9f3c028f%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.