#29340: "cache.get_or_set()" extra hits on database
------------------------------------------------+------------------------
               Reporter:  hematinik             |          Owner:  nobody
                   Type:  Cleanup/optimization  |         Status:  new
              Component:  Core (Cache system)   |        Version:  2.0
               Severity:  Normal                |       Keywords:  cache
           Triage Stage:  Unreviewed            |      Has patch:  0
    Needs documentation:  0                     |    Needs tests:  0
Patch needs improvement:  0                     |  Easy pickings:  0
                  UI/UX:  0                     |
------------------------------------------------+------------------------
 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.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29340>
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/052.7e3e089432d7dc2136faa1854cce505e%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to