#29340: "cache.get_or_set()" extra hits on database
-------------------------------------+-------------------------------------
Reporter: hematinik | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Core (Cache system) | Version: 2.0
Severity: Normal | Resolution:
Keywords: cache | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by hematinik:
Old description:
> I've found out that using {{{cache.get_or_set()}}} causes extra SQL
> queries while using the alternative approach to get a key’s value or set
> a value if the key isn’t in the cache (using "if" statement) works fine
> without extra hits on database.
> it seems the problem appears when you use the {{{cache.get_or_set()}}}
> inside a loop . this is the code to reproduce the problem:
>
> THE MODEL:
>
> {{{
> #!python
>
> class EventManager(models.Manager):
>
> def get_location(self,event):
>
> output = cache.get_or_set(
> 'event_location_eID{}'.format(event.pk),
> event.location,
> None)
>
> return output
>
> class Event(models.Model):
>
> objects = EventManager()
> location = models.ForeignKey(Location,on_delete = models.CASCADE)
>
> }}}
>
> THE VIEW:
> {{{
> #!python
> def home(request):
>
> events = cache.get_or_set('all_events',Event.objects.all(),None) #
> this line works fine without extra hits on db
> locations = []
>
> for event in events:
> x = Event.objects.get_location(event) # this line causes extra
> SQL queries while the cache keys already exist
> locations.append(x)
>
> return render(request,'index.html',{'locations':locations})
> }}}
>
> THE TEMPLATE:
> {{{
> #!python
> {% for location in locations %}
>
> {{location.title}} <br>
>
> {% endfor %}
> }}}
>
> now if I change the {{{get_location()}}} method on {{{EventManager}}} to
> this:
>
> {{{
> #!python
> def get_location(self,event):
>
> output = cache.get('event_location_eID{}'.format(event.pk))
> if output is None:
> output = event.location
> cache.set('event_location_eID{}'.format(event.pk),output,None)
>
> return output
> }}}
>
> there will be no more unnecessarily SQL queries.
>
> I'm using **django-debug-toolbar** to monitor my database requests and
> the information about queries is based on the statistics that **django-
> debug-toolbar** provides. I'll also attach some screenshots from
> **django-debug-toolbar** to clarify the situation.
>
> Regards.
New description:
I've found out that using {{{cache.get_or_set()}}} causes extra SQL
queries while using the alternative approach to get a key’s value or set a
value if the key isn’t in the cache (using "if" statement) works fine
without extra hits on database.
it seems the problem appears when you use the {{{cache.get_or_set()}}}
inside a loop . this is the code to reproduce the problem:
THE MODEL:
{{{
#!python
class EventManager(models.Manager):
def get_location(self,event):
output = cache.get_or_set(
'event_location_eID{}'.format(event.pk),
event.location,
None)
return output
class Event(models.Model):
objects = EventManager()
location = models.ForeignKey(Location,on_delete = models.CASCADE)
}}}
THE VIEW:
{{{
#!python
def home(request):
events = cache.get_or_set('all_events',Event.objects.all(),None) #
this line works fine without extra hits on db
locations = []
for event in events:
x = Event.objects.get_location(event) # this line causes extra SQL
queries while the cache keys already exist
locations.append(x)
return render(request,'index.html',{'locations':locations})
}}}
THE TEMPLATE:
{{{
#!python
{% for location in locations %}
{{location.title}} <br>
{% endfor %}
}}}
now if I change the {{{get_location()}}} method on {{{EventManager}}} to
this:
{{{
#!python
def get_location(self,event):
output = cache.get('event_location_eID{}'.format(event.pk))
if output is None:
output = event.location
cache.set('event_location_eID{}'.format(event.pk),output,None)
return output
}}}
there will be no more unnecessarily SQL queries.
I'm using **django-debug-toolbar** to monitor my database requests and the
information about queries is based on the statistics that **django-debug-
toolbar** provides. I'll also attach some screenshots from **django-
debug-toolbar** to clarify the situation.
sql queries when using {{{get_or_set()}}}: [https://imgur.com/a/dydWEuL]
sql queries when using the alternative approach :
[https://imgur.com/a/vYpfUZ3]
Regards.
--
--
Ticket URL: <https://code.djangoproject.com/ticket/29340#comment:1>
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/067.87fa8f883dff7f40e6c984cae2257108%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.