# HG changeset patch # User Brian Neal # Date 1300925734 0 # Node ID 9af6bd45c1f8ff2191fae1881472c8e9d3f3d9d4 # Parent 79240675b903497c5f05b70eed506a706546b99c Another try at #191 after getting some good advice in a django-users thread. diff -r 79240675b903 -r 9af6bd45c1f8 gpp/forums/feeds.py --- a/gpp/forums/feeds.py Wed Mar 23 02:02:44 2011 +0000 +++ b/gpp/forums/feeds.py Thu Mar 24 00:15:34 2011 +0000 @@ -4,8 +4,7 @@ from django.core.exceptions import ObjectDoesNotExist from django.shortcuts import get_object_or_404 -from forums.models import Forum -from forums.models import Post +from forums.models import Forum, Topic, Post from core.functions import copyright_str @@ -55,27 +54,24 @@ def items(self, obj): if obj is None: # return a combined feed of public forum threads - # - # This didn't work real well on InnoDb: - # items = Post.objects.filter( - # topic__forum__in=Forum.objects.public_forums()) - # - # For some reason, MySQL wasn't using an index when "in" was used. - # So let's do this the hard way as a work-around: - public_forum_ids = Forum.objects.public_forum_ids() - posts = [] - for forum_id in public_forum_ids: - posts.extend(list(Post.objects.filter( - topic__forum=forum_id).order_by('-creation_date').select_related( - 'topic', 'user', 'topic__forum')[:30])) + # This was tricky to do without suffering a large performance + # impact. Because the number of forums is small, MySQL did not + # try to use an index and ended up searching all the topics for + # candidate posts. We work around this first getting a small list + # of candidate topics, and then searching them. This is more + # queries but a *lot* more time efficient. - posts.sort(key=lambda x: x.creation_date, reverse=True) - return posts[:30] + forum_ids = Forum.objects.public_forum_ids() + topic_ids = list(Topic.objects.filter(forum__in=forum_ids).order_by( + '-update_date').values_list('id', flat=True)[:30]) + items = Post.objects.filter(topic__in=topic_ids) else: - return Post.objects.filter(topic__forum__id=obj.id).order_by( - '-creation_date').select_related('topic', 'user', 'topic__forum')[:30] + items = Post.objects.filter(topic__forum=obj) + + return items.order_by('-creation_date').select_related('topic', 'user', + 'topic__forum')[:30] def item_title(self, item): return item.topic.name diff -r 79240675b903 -r 9af6bd45c1f8 gpp/forums/models.py --- a/gpp/forums/models.py Wed Mar 23 02:02:44 2011 +0000 +++ b/gpp/forums/models.py Thu Mar 24 00:15:34 2011 +0000 @@ -202,7 +202,7 @@ # denormalized fields to reduce database hits post_count = models.IntegerField(blank=True, default=0) - update_date = models.DateTimeField() + update_date = models.DateTimeField(db_index=True) last_post = models.OneToOneField('Post', blank=True, null=True, related_name='parent_topic')