You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何提升Django中QuerySet分页性能?分页耗时过长求助

Django QuerySet分页性能优化方案

你的分页代码存在冗余数据库查询、不必要的数据加载等问题,结合你提供的耗时截图:
query time and pagination time

以下是针对性的优化手段:

  • 移除重复计数查询
    你手动执行了query_set.count(),但Paginator内部计算num_pages时会再次发起COUNT查询,导致两次相同的数据库请求。直接删除冗余的total_rows = query_set.count(),改用paginator.count获取总条数即可。

  • 优化QuerySet的数据库访问
    解决潜在的N+1查询问题:

    • 对一对一/外键关联字段,使用select_related()提前加载关联数据
    • 对多对多/反向外键关联字段,使用prefetch_related()批量加载
      同时用only()指定仅需要返回的字段,减少数据传输和内存占用,示例:
    query_set = YourModel.objects.select_related('related_model').only('id', 'title', 'related_model__name')
    
  • 避免强制转换Page对象为列表
    paginator.get_page(page_number)返回的Page对象本身是懒加载的,无需转成list。强制转换会触发所有对象的立即加载,增加内存消耗和处理时间,直接使用Page对象进行序列化返回即可。

  • 大数据量场景改用游标分页
    如果你的数据集量级较大(百万级以上),普通Paginator依赖的LIMIT/OFFSET分页在页码较大时,数据库需要扫描大量前置数据后丢弃,性能急剧下降。此时可改用基于游标的分页方式:

    • 若使用Django REST Framework,直接使用CursorPagination
    • 自定义实现时,基于唯一有序字段(如id、created_at),以上一页最后一条数据的字段值作为游标,查询下一页数据,避免OFFSET的性能瓶颈。
  • 优化后的代码示例

    query_end_time = time.time() - start
    print(query_end_time, "query_end_time")
    
    paginator = Paginator(query_set, number_of_rows)
    number_of_pages = paginator.num_pages
    total_rows = paginator.count  # 从paginator直接获取总条数,避免重复查询
    
    page_number = request.GET.get("page_number")
    # 无需转成list,直接使用Page对象
    order_item = paginator.get_page(page_number)
    
    pagination_end_time = time.time() - start
    print(pagination_end_time, "pagination_end_time")
    

内容的提问来源于stack exchange,提问作者Praveen Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 19:42:44