#25375: Paginator generates suboptimal queries
----------------------------------------------+--------------------
     Reporter:  alexei                        |      Owner:  nobody
         Type:  Bug                           |     Status:  new
    Component:  Database layer (models, ORM)  |    Version:  1.7
     Severity:  Normal                        |   Keywords:
 Triage Stage:  Unreviewed                    |  Has patch:  0
Easy pickings:  0                             |      UI/UX:  0
----------------------------------------------+--------------------
 Hello,

 I'm using Django Rest Framework and have the following situation:

 I have two models, `Article` and `Comment`:

 {{{
 class Article(models.Model):
     # ...

 class Comment(models.Model):
     article = models.ForeignKey(Article, related_name='comments')
     # ...

 }}}

 And an articles viewset:

 {{{
 class Articles(viewsets.ModelViewSet):
     model = Article
     serializer_class = ArticleSerializer
     paginate_by = 50
     paginate_by_param = 'limit'

     def get_queryset(self):
         return Article.objects.annotate(comments_count=Count('comments'))
 }}}

 When doing a simple listing, the database will be queried two times: one
 to count the result set, the other to fetch the results:

 {{{
 SELECT
     COUNT(*)
     FROM (
         SELECT
             `article`.`id` AS `id`,
             COUNT(`article_comment`.`id`) AS `comments_count`
         FROM `article`
         LEFT OUTER JOIN `article_comment` ON (`article`.`id` =
 `article_comment`.`article_id`)
         GROUP BY `article`.`id`
         ORDER BY NULL
     )
     subquery;
 }}}

 And

 {{{
 SELECT
     `article`.`id` AS `id`,
     COUNT(`article_comment`.`id`) AS `comments_count`
 FROM `article`
 LEFT OUTER JOIN `article_comment` ON (`article`.`id` =
 `article_comment`.`article_id`)
 GROUP BY `article`.`id`
 ORDER BY `article`.`id` DESC
 LIMIT 50;
 }}}
 respectively.

 If you look at (and `EXPLAIN`) the first query, the one that does the
 counting, you'll notice it loads up *all* records and then starts counting
 them, a process which may take up all resources and eventually crash the
 machine. It did so in my case, with only 50000 records.

 I figured this has something to do with Django, not DRF.

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

Reply via email to