当前位置:

首页 > 编程开发 > Django 6.1 RC1 实测:FETCH_PEERS 两条 SQL 解决 N+1,select_related 还需要吗?

Django 6.1 RC1 实测:FETCH_PEERS 两条 SQL 解决 N+1,select_related 还需要吗?

本文目录

    Django 6.1 RC1 实测:FETCH_PEERS 两条 SQL 解决 N+1,select_related 还需要吗? Django 6.1 RC1 在 2026 年 7 月 22 日发布,正式版已进入最后的发布窗口。这个版本最值得后端开发者关注的变化之一,是 ORM 新增了 Fetch

    Django 6.1 RC1 实测:FETCH_PEERS 两条 SQL 解决 N+1,select_related 还需要吗?

    Django 6.1 RC1 在 2026 年 7 月 22 日发布,正式版已进入最后的发布窗口。这个版本最值得后端开发者关注的变化之一,是 ORM 新增了 Fetch Modes(字段获取模式)。

    它试图解决一个老问题:代码运行时才访问关联字段,开发者又没有提前写 select_related() 或 prefetch_related(),于是一次列表查询悄悄膨胀成 N+1 条 SQL。

    这篇文章不只介绍 API。我在隔离环境中安装了 Django 6.1 RC1,用 100 本书和 100 位作者做了一次可复现实验,直接比较:

    • 默认的 FETCH_ONE;
    • 新增的 FETCH_PEERS;
    • 传统的 select_related();
    • 用来阻止意外查询的 RAISE。

    先给结论:FETCH_PEERS 很有价值,但它不是 select_related() 的替代品。

    N+1 为什么总在代码评审后才暴露

    假设每本书都关联一位作者:

     复制代码class Author(models.Model):
        name = models.CharField(max_length=100)
    class Book(models.Model):
        title = models.CharField(max_length=200)
        author = models.ForeignKey(Author, on_delete=models.CASCADE)
    

    下面的代码看起来非常自然:

     复制代码books = Book.objects.all()for book in books:
        print(book.author.name)
    

    第一条 SQL 查询 100 本书。之后,每次访问 book.author,Django 都需要再查询一次作者,于是总数变成:

     复制代码1 条 Book 查询 + 100 条 Author 查询 = 101 条 SQL
    

    传统修复方式是提前声明关联字段:

     复制代码books = Book.objects.select_related("author")
    

    它会使用 JOIN,一条 SQL 就把书和作者一起取回。问题在于,真实系统中的字段访问经常由序列化器、模板、插件或运行时分支决定,写查询的人未必知道后面会访问哪个字段。

    这正是 FETCH_PEERS 想补上的空白。

    Django 6.1 的三种 Fetch Mode

    FETCH_ONE:保持原来的行为

     复制代码from django.db import modelsbooks = Book.objects.fetch_mode(models.FETCH_ONE)
    

    当一个未加载字段被访问时,只为当前对象取一次数据。这是 Django 过去的行为,也是 Django 6.1 的默认模式。

    优点是行为稳定、单次访问成本明确;缺点是放进循环后很容易形成 N+1。

    FETCH_PEERS:第一次访问时批量补齐同批对象

     复制代码books = Book.objects.fetch_mode(models.FETCH_PEERS)for book in books:
        print(book.author.name)
    

    第一次访问某一本书的 author 时,Django 会找到来自同一个 QuerySet 的其他 Book 实例,并批量获取它们需要的关联作者。最终查询形态通常是:

    1. 查询全部 Book;
    2. 批量查询这些 Book 对应的 Author。

    它很像“按需触发的 prefetch_related()”:只有代码真正访问关联字段时,第二条查询才发生。

    RAISE:不允许代码偷偷访问数据库

     复制代码books = Book.objects.fetch_mode(models.RAISE)for book in books:
        print(book.author.name)
    

    一旦 author 未能提前加载,Django 便不再默默执行查询,而是直接抛出 FieldFetchBlocked 异常。这一机制在性能敏感场景、模板渲染及 API 序列化测试中显得尤为关键:它让意外产生的 SQL 无法再悄无声息地溜过,而是立刻报错,从而确保代码行为的确定性。

    100 本书的真实查询结果

    测试环境如下:

    项目配置
    Django6.1 RC1
    Python3.12
    数据库SQLite 内存数据库
    数据量100 Author + 100 Book
    关系每本书关联一位作者
    计数方法connection.queries

    核心测试函数只有几行:

     复制代码def measure(label, queryset):
        connection.queries_log.clear()
        started = perf_counter()
        books = list(queryset)
        names = [book.author.name for book in books]
        elapsed_ms = (perf_counter() - started) * 1000
        print(label, len(connection.queries), elapsed_ms)
    

    四种模式依次运行:

     复制代码measure("FETCH_ONE", Book.objects.fetch_mode(models.FETCH_ONE))
    measure("FETCH_PEERS", Book.objects.fetch_mode(models.FETCH_PEERS))
    measure("select_related", Book.objects.select_related("author"))blocked = list(Book.objects.fetch_mode(models.RAISE))
    print(blocked[0].author.name)  # FieldFetchBlocked
    

    本机单次结果如下:

    策略SQL 数量单次耗时
    FETCH_ONE10123.74 ms
    FETCH_PEERS23.09 ms
    select_related11.26 ms
    RAISE阻止查询抛出 FieldFetchBlocked

    这组数据更适合用来说明查询形态,本身并不能直接当作通用性能排行榜来看。原因很简单:SQLite 的内存数据库、数据规模、字段宽度、网络延迟,甚至数据库执行计划,都会把最终耗时拉向不同结果。真正更稳、更有参考价值的结论,其实是 SQL 的数量变化——在这个关系访问场景里,FETCH_PEERS 直接把 101 条 SQL 压缩到了 2 条。

    select_related 还需要吗?当然需要

    如果业务代码明确知道“这次一定会访问作者”,select_related("author") 仍然是最直接的表达:

     复制代码books = Book.objects.select_related("author")
    

    它的优势有三个:

    1. 查询意图在代码中清晰可见;
    2. 只执行一次 JOIN;
    3. 不需要等到第一次属性访问时才触发第二条 SQL。

    FETCH_PEERS 更适合访问路径不确定的场景。例如:

    • 同一个 QuerySet 被多个序列化器复用;
    • 模板根据权限决定是否展示关联字段;
    • 插件或扩展在运行时访问模型属性;
    • 希望减少 N+1,又不想为每条动态路径维护预取字段列表。

    换句话说,select_related() 是“我明确知道会用什么”;FETCH_PEERS 是“我运行到这里才知道需要什么,但请不要逐条查询”。

    一张图完成策略选择

    可以把选型压缩成三条规则:

    规则一:字段明确且必用,优先 select_related

    对于 ForeignKey 和 OneToOneField,如果调用链明确,JOIN 通常更直接。

    规则二:访问由运行时决定,考虑 FETCH_PEERS

    它能在真正访问字段时批量补齐同一 QuerySet 的对象,避免逐条获取。

    规则三:性能边界必须严格,使用 RAISE

    把隐式查询变成测试失败,尤其适合高吞吐 API、循环和模板渲染边界。

    FETCH_PEERS 的边界不能忽略

    第一,它只影响未加载字段和关联对象的获取行为,不会让任意 ORM 查询自动变快。

    第二,它不是数据库缓存。第二条批量查询仍然真实发生,只是从 N 条缩减为一条。

    第三,模式会沿着获取到的关联对象继续传播。复杂关系树中应观察真实 SQL,而不是凭感觉判断。

    第四,Django 6.1 RC1 仍是预发布版本。正式版发布前,API 与边界行为仍应以最终文档和发布说明为准,生产环境不要因为一篇基准文章直接升级。

    升级前的验证清单

    • 在隔离环境安装 Django 6.1 RC1,不直接修改生产依赖;
    • 为关键列表接口记录 SQL 数量基线;
    • 对已知字段继续使用 select_related() / prefetch_related();
    • 在动态访问路径试用 FETCH_PEERS;
    • 在不允许隐式查询的测试中启用 RAISE;
    • 同时比较 SQL 数量、返回数据量和数据库执行计划;
    • 检查第三方包是否支持 Django 6.1;
    • 正式升级前重新阅读最终版 6.1 发布说明。

    结论:FETCH_PEERS 是新工具,不是万能替代

    Django 6.1 没有宣布 select_related() 过时。它新增的是一套更细的控制手段:

    • FETCH_ONE 保留兼容行为;
    • FETCH_PEERS 在运行时批量补齐同批对象;
    • RAISE 把意外 SQL 变成明确错误;
    • select_related() 继续负责已知关系的主动 JOIN。

    真正值得升级的不是“少写一个 select_related”,而是 ORM 第一次允许我们明确表达:缺失字段应该单独取、成批取,还是根本不许取。

    如果你的项目中既有 DRF 序列化器又有复杂模板,你更希望先在哪一层尝试 FETCH_PEERS?

    参考资料

    • Django 6.1 RC1 发布公告
    • Django 6.1 Fetch Modes 官方文档
    • Django 6.1 发布说明
    本文内容来源于网友投稿,如有侵权请联系删除。
    作者最新文章
    编程开发
    相关文章 更多
    Claude Code AI编程工具实力揭秘与编程助手实测
    Claude Code AI编程工具实力揭秘与编程助手实测

    通过实测展示Claude Code在终端中如何理解自然语言指令、自动修改代码文件并处理复杂编程任务,帮助开发者评估其实际辅助能力。

    winforms教程自学入门与基础开发步骤详解
    winforms教程自学入门与基础开发步骤详解

    本教程详细讲解如何使用Visual Studio创建WinForms项目,通过添加按钮和标签控件并编写点击事件代码,实现一个基础的计数器功能,适合C#初学者快速上手Windows窗体应用开发。

    Cursor自动补全设置教程教你快速开启代码补全功能
    Cursor自动补全设置教程教你快速开启代码补全功能

    详解Cursor编辑器中自动补全功能的开启与优化设置,涵盖Tab触发机制、上下文窗口调整及模型切换,帮助开发者解决补全延迟、干扰大等问题,提升编码流畅度。

    pandas的数据格式怎么转换和设置方法教程
    pandas的数据格式怎么转换和设置方法教程

    详解Pandas中数据格式转换的核心方法,包括astype强制转换、to_numeric容错处理及日期解析技巧,解决常见类型错误并提升数据处理效率。

    VS Code中文设置方法 简体语言包安装与切换教程
    VS Code中文设置方法 简体语言包安装与切换教程

    详细介绍在Visual Studio Code中安装Chinese (Simplified)语言包的方法,包括通过扩展市场搜索、安装及自动重启切换至简体中文界面的完整步骤,帮助开发者快速将编辑器本地化。

    cursor安装过程无法更改安装位置的解决方法
    cursor安装过程无法更改安装位置的解决方法

    针对Cursor安装包默认锁定C盘且无路径选择界面的问题,提供通过手动移动文件并创建目录联结(Symbolic Link)的解决方案,实现将软件安装在其他磁盘分区。

    rust下载安装教程详解及Windows环境配置方法
    rust下载安装教程详解及Windows环境配置方法

    详解Windows系统下Rust语言的安装步骤,重点解析rustup工具链管理机制,解决环境变量配置错误及MSVC链接器缺失问题,提供可复制的命令验证方法与常见报错的因果排查思路。

    vs code怎么配置 chat实用设置教程步骤
    vs code怎么配置 chat实用设置教程步骤

    详解VS Code中Chat插件的安装与核心配置步骤,重点解决API连接失败、响应慢等常见问题,通过优化上下文设置提升代码生成质量,适合希望集成AI辅助工具的开发者阅读。

    uniapp实例教程代码详解与项目实战指南
    uniapp实例教程代码详解与项目实战指南

    本教程通过实战案例详解UniApp开发流程,包括项目初始化、页面结构解析、数据绑定与事件处理,帮助初学者快速上手跨平台应用开发。

    android studio安装教程2026
    android studio安装教程2026

    详细讲解2026年最新版Android Studio的下载与安装步骤,涵盖JDK环境检查、组件选择及初始配置,助您顺利开启安卓应用开发之旅。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    macOS软件
    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    Mac软件 更多
    Blender
    Blender
    Windows、macOS 和 Linux

    Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。

    灵活计算器
    灵活计算器
    macOS/iOS/Android

    灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

    赤友清理大师
    赤友清理大师
    macOS

    赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

    WINDOWS 更多
    Blender
    Blender
    Windows、macOS 和 Linux

    Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。

    Windows 10
    Windows 10
    Windows

    Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

    极度公式
    极度公式
    Windows/macOS/Linux

    极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。