【问题标题】:MySQL database being hit too many times with django queryMySQL 数据库被 django 查询命中太多次
【发布时间】:2011-12-29 12:09:23
【问题描述】:

我正在使用 django-favorites 来拉取用户喜欢的对象列表。该应用程序有一个模型和一个管理器

class FavoriteManager(models.Manager):
    """ A Manager for Favorites
    """
    def favorites_for_user(self, user):
        """ Returns Favorites for a specific user
        """
        return self.get_query_set().filter(user=user)

class Favorite(models.Model):
    user = models.ForeignKey(User)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    created_on = models.DateTimeField(auto_now_add=True)

    objects = FavoriteManager()

    class Meta:
        verbose_name = _('favorite')
        verbose_name_plural = _('favorites')
        unique_together = (('user', 'content_type', 'object_id'),)

    def __unicode__(self):
        return "%s added %s as a favorite" % (self.user, self.content_object)

在我看来,我是在为用户拉最爱

 from favorites.models import Favorite
 def myfavorites(request):

      item = Favorite.objects.favorites_for_user(user=request.user)

      return render_to_response('myfavorites.html', {
           'favorites':item
      },
      context_instance=RequestContext(request))

在我的模板中,我尝试获取收藏夹列表及其模型类型:

{% for fave in favorites %}
    {{ fave.content_type }}<br>
    {{ fave.content_object }}<br><br>
{% endfor %}

但是使用 django 调试工具栏,我看到我在每个循环中都访问了数据库两次。该代码正在数据库中查询收藏夹对象中每个收藏的 content_type 和 content_object。

如何优化代码,以便一次提取数据而不需要多次访问数据库来检索信息?

【问题讨论】:

    标签: python mysql django


    【解决方案1】:

    您可以选择几种解决方案:

    1. 通用关系预取,你可以像example app这样使用this snippet

    2. Identity map/caching,使用内容类型和对象id做key来缓存模型,这里是an example你可以取__getstate__和@里面的代码987654329@并做一个模板标签,这是你能找到的最快的解决方案

    3. 直接获取关系,稍后在使用外键时,您可能需要使用article about generic relation performance 中详述的解决方案之一。

    4. 使用 JonhyCacheJohnyCache 是一个用于查询集的缓存框架,它与 django 缓存抽象配合使用。我还没有亲自尝试过,因为这三种解决方案在我的项目中已经足够了。

    5. 缓存模板片段,不那么hacky,它看起来像official way to deal with this kind of issue,会产生很多查询,当用户更改他的收藏夹时,你可以invalidate the cached version

    请注意,select_related() 不适用于泛型关系。这是因为相关对象可以在 any 表中,因此不可能在纯 sql 中进行正确的连接。泛型关系是 Django 的一个特性,而不是 MySQL。

    【讨论】:

      【解决方案2】:

      尝试使用select_related 查询集方法。

      这样的事情应该可以解决问题:

      item = Favorite.objects.favorites_for_user(user=request.user).select_related('content_type', 'content_object')
      

      编辑:jpic 正确地指出 select_related 不适用于“content_object”,因为它是通用外键。不幸的是,没有很好的内置方法来处理这个问题,而且在 Django 1.4 推出之前不会有。同时,请查看this SO question 以获取一些建议。 jpic 在他的回答中也发布了一些很好的解决方案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-15
        • 2020-12-25
        • 2016-09-21
        • 2011-02-15
        相关资源
        最近更新 更多