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

如何修复获取对象集合数据时的Django N+1查询问题

解决Django中的N+1查询问题

原代码的问题在于循环调用get_or_create,每遍历一个CustomUser就发起一次数据库查询,当数据量较大时会导致严重的性能问题(1次查询获取所有sponsor用户,加上N次查询单个Sponsor记录,即N+1查询)。

优化方案:批量处理查询与创建

通过批量查询已存在的Sponsor记录,再批量创建缺失的记录,将查询次数压缩到固定的3-4次,彻底解决N+1问题:

# 1. 获取目标用户列表
sponsors = CustomUser.objects.filter(user_type=2, is_deleted=False)
if not sponsors.exists():
    # 没有用户时直接返回,避免后续无效操作
    return

# 2. 提取用户ID,批量查询已存在的Sponsor记录
sponsor_ids = [s.id for s in sponsors]
existing_sponsors = Sponsor.objects.filter(user_id__in=sponsor_ids, is_deleted=False)

# 3. 将已存在的Sponsor按用户ID做映射,方便快速查找
sponsor_map = {sp.user_id: sp for sp in existing_sponsors}

# 4. 收集需要创建的Sponsor记录
to_create = []
for s in sponsors:
    if s.id not in sponsor_map:
        to_create.append(Sponsor(user=s, is_deleted=False))

# 5. 批量创建缺失的记录
if to_create:
    Sponsor.objects.bulk_create(to_create)

# 6. 更新映射,包含刚创建的记录
updated_sponsors = Sponsor.objects.filter(user_id__in=sponsor_ids, is_deleted=False)
sponsor_map = {sp.user_id: sp for sp in updated_sponsors}

# 7. 为每个用户赋值sponsor_detail
for s in sponsors:
    s.sponsor_detail = sponsor_map[s.id]

优化说明

  • 批量查询:用user_id__in一次获取所有已关联的Sponsor,替代循环中的单次查询
  • 批量创建:用bulk_create一次性插入多条记录,比循环调用create效率高得多
  • 映射查找:通过字典映射快速匹配用户与Sponsor,避免重复查询

内容的提问来源于stack exchange,提问作者Shaheem PP

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 22:00:53