diff gpp/forums/feeds.py @ 387:b15726767ab8

Fixing #191; terrible performance on the combined forums RSS feed query. Use an .extra() clause to force the WHERE on a query to use the primary key.
author Brian Neal <bgneal@gmail.com>
date Sat, 19 Mar 2011 01:52:41 +0000
parents 2a03c69792d8
children c3231af55778
line wrap: on
line diff
--- a/gpp/forums/feeds.py	Thu Mar 17 01:20:23 2011 +0000
+++ b/gpp/forums/feeds.py	Sat Mar 19 01:52:41 2011 +0000
@@ -20,7 +20,7 @@
         # only return public forums
         if forum_slug:
             forum = get_object_or_404(Forum, slug=forum_slug)
-            if forum.category.groups.count() > 0:
+            if forum.id not in Forum.objects.public_forum_ids():
                 raise ObjectDoesNotExist
             return forum
 
@@ -55,11 +55,27 @@
     def items(self, obj):
         if obj is None:
             # return a combined feed of public forum threads
-            items = Post.objects.filter(
-                    topic__forum__in=Forum.objects.public_forums())
+            #
+            # This didn't work real well on InnoDb:
+            # items = Post.objects.filter(
+            #         topic__forum__in=Forum.objects.public_forums())
+            #
+            # The where clause in the generated SQL looked like this:
+            #   WHERE `forums_topic`.`forum_id` IN ( ... )
+            # This was terrible for performance. This does much better:
+            #   WHERE `forums_topic`.`id` IN ( ... )
+            #
+            # So we use Django's .extra() to force the above.
+
+            public_forum_ids = Forum.objects.public_forum_ids()
+            ids = ','.join(str(pub) for pub in public_forum_ids)
+
+            items = Post.objects.extra(
+                where=['forums_topic.id in (%s)' % ids])
+
         else:
             items = Post.objects.filter(topic__forum__id=obj.id)
-        return items.order_by('-creation_date').select_related()[:30]
+        return items.order_by('-creation_date').select_related(depth=2)[:30]
 
     def item_title(self, item):
         return item.topic.name