How to avoid n+1 select in django?

后端 未结 3 644
日久生厌
日久生厌 2021-02-05 18:01

I have a very simple datamodel with a one to many relationship between video and comments

class Video(models.Model):
    url = models.URLField(unique=True)
    .         


        
相关标签:
3条回答
  • 2021-02-05 18:48

    For ForeignKey, you can use selected_related():

    Comment.objects.select_related('video').all()
    

    It will generate one query only, gathering coments for you as well as videos.

    For something more complex (such as M2M), you need an external app such as unjoinify to make optimizations but it uses SQL queries to then put them back in objects.

    If you are unconfortable with this (I am), you have some alternatives:

    • django-queryset-transform: not a full solution, but helps
    • django-batch-select: roughtly a select_related that works with M2M and reverse relations.
    0 讨论(0)
  • 2021-02-05 18:57

    See if select related works the way you expect it to, it was made just for that.

    0 讨论(0)
  • 2021-02-05 19:04

    What you need to do is use the select_related on the Comment.

    Lets say you need to find the all the videos whose title starts with 'The' and the comments related to it

    comments = Comment.objects.filter(video__title__starts_with='The')
               .select_related('video').all()
    

    This will load all the comments and the appropriate Video object for that comment. You will still need to pivot over the Video to iterate over the videos. Use the python itertools.groupby function to do that pivoting in memory.

    0 讨论(0)
提交回复
热议问题