Django 查询集的 count 调用有多昂贵?

How expensive are `count` calls for Django querysets?

我有一个 "posts" 列表,我必须渲染。对于每个 post,我必须执行三个过滤器查询集,或将它们组合在一起,然后计算对象的数量。这合理吗?哪些因素可能会导致速度变慢?

这大概是我的代码:

def viewable_posts(request, post):

    private_posts = post.replies.filter(permissions=Post.PRIVATE, author_profile=request.user.user_profile).order_by('-modified_date')
    community_posts = post.replies.filter(permissions=Post.COMMUNITY, author_profile__in=request.user.user_profile.following.all()).order_by('-modified_date')
    public_posts = post.replies.filter(permissions=Post.PUBLIC).order_by('-modified_date')

    mixed_posts = private_posts | community_posts | public_posts

    return mixed_posts

def viewable_posts_count(request, post):

    return viewable_posts(request, post).count()

我能看到的最大因素是您对每个 post 都有过滤操作。如果可能,您应该在一个查询中查询与每个 post 关联的结果。从 count 开始,这是从查询中获取结果数量的最有效方式,因此这可能不是问题。

试试下面的代码:

def viewable_posts(request, post):

    private_posts = post.replies.filter(permissions=Post.PRIVATE, author_profile=request.user.user_profile).values_list('id',flat=True)
    community_posts = post.replies.filter(permissions=Post.COMMUNITY, author_profile__in=request.user.user_profile.following.values_list('id',flat=True)
    public_posts = post.replies.filter(permissions=Post.PUBLIC).values_list('id',flat=True)

   Lposts_id = private_posts
   Lposts_id.extend(community_posts)
   Lposts_id.extend(public_posts)

   viewable_posts  = post.filter(id__in=Lposts_id).order_by('-modified_date')
   viewable_posts_count  = post.filter(id__in=Lposts_id).count()

   return viewable_posts,viewable_posts_count

它应该改进以下内容:

  1. order_by一次,而不是三次
  2. count 方法在只有索引字段的查询上运行
  3. django 使用 "values" 更快的过滤器,用于计数和过滤。
  4. 取决于您的数据库,数据库自己的缓存可能会选择 viewable_posts 的最后查询帖子,并将其用于 viewable_posts_count

确实,如果您可以将前三个筛选查询压缩为一个,您也可以节省时间。