Django-ORM-prefetch_related

Django-ORM-prefetch_related

  • 模型定义
    • N+1 查询问题示例
  • 使用 prefetch_related 优化查询
  • 处理更复杂的查询
    • 示例:预取特定条件的书籍
    • 示例:预取多个关联字段
  • 性能比较
  • 注意事项
  • 总结

通过 AuthorBooks 两个模型来理解 Django 的 prefetch_related 方法。
探讨如何使用 prefetch_related 来优化查询,避免 N+1 查询问题,
并展示其在处理多对多关系和复杂查询中的强大功能。

模型定义

首先,假设我们有两个模型:AuthorBook。一个作者可以写多本书,一本书也可以有多个作者(多对多关系)。

from django.db import modelsclass Author(models.Model):name = models.CharField(max_length=100)def __str__(self):return self.nameclass Book(models.Model):title = models.CharField(max_length=100)authors = models.ManyToManyField(Author, related_name='books')def __str__(self):return self.title

N+1 查询问题示例

假设我们想要获取所有作者以及他们所写的书籍。
如果不使用 prefetch_related,可能会遇到 N+1 查询问题。

# 获取所有作者
authors = Author.objects.all()for author in authors:print(f"Author: {author.name}")for book in author.books.all():  # 每个作者都会触发一次数据库查询print(f"  Book: {book.title}")

问题分析:
• 第一次查询获取所有作者。
• 对于每个作者,执行一次查询来获取其书籍。
• 如果有 10 个作者,总共会执行 1 + 10 = 11 次查询。

使用 prefetch_related 优化查询

prefetch_related 可以显著减少查询次数。
它会在后台执行额外的查询,并将结果缓存起来,
以便在访问关联对象时不需要额外的数据库查询。

# 使用 prefetch_related 预取每个作者的书籍
authors = Author.objects.prefetch_related('books')for author in authors:print(f"Author: {author.name}")for book in author.books.all():  # 现在只执行两次查询print(f"  Book: {book.title}")

优化效果:
• 第一次查询获取所有作者。
• 第二次查询获取所有相关的书籍。
• Django 在 Python 层面将这些书籍分配给相应的作者。
• 总共只执行了 2 次查询,无论有多少个作者。

处理更复杂的查询

有时候,我们可能需要预取多个关联字段,或者对预取的数据进行过滤。
这时,可以使用 Prefetch 对象来实现更细粒度的控制。

示例:预取特定条件的书籍

假设我们只想预取每位作者最近出版的 5 本书:

from django.db.models import Prefetch# 定义一个 Prefetch 对象,过滤并限制预取的书籍数量
recent_books = Prefetch('books',queryset=Book.objects.order_by('-id')[:5], # 假设 id 越大,出版时间越近to_attr='recent_books'                     # 将预取的书籍存储在 author.recent_books 中
)authors = Author.objects.prefetch_related(recent_books)for author in authors:print(f"Author: {author.name}")for book in author.recent_books:  # 访问预取的书籍print(f"  Recent Book: {book.title}")

解释:
• 使用 Prefetch 对象,我们可以自定义预取的查询集。
to_attr 参数指定了预取的数据存储在模型实例的哪个属性中。
• 这样可以避免加载所有关联对象,只加载我们需要的部分。

示例:预取多个关联字段

如果 Author 模型还有其他关联字段,比如 editor,我们可以同时预取多个关联:

authors = Author.objects.prefetch_related('books','editor'  # 假设有一个 ForeignKey 字段 'editor'
)for author in authors:print(f"Author: {author.name}")for book in author.books.all():print(f"  Book: {book.title}")if author.editor:print(f"  Editor: {author.editor.name}")

性能比较

为了更直观地理解 prefetch_related 的性能优势,我们来看一个简单的性能对比:

import time# 不使用 prefetch_related
start_time = time.time()
authors = Author.objects.all()
for author in authors:for book in author.books.all():pass  # 模拟操作
end_time = time.time()
print(f"无 prefetch_related 查询次数: {end_time - start_time} 秒")# 使用 prefetch_related
start_time = time.time()
authors = Author.objects.prefetch_related('books')
for author in authors:for book in author.books.all():pass  # 模拟操作
end_time = time.time()
print(f"使用 prefetch_related 查询次数: {end_time - start_time} 秒")

预期结果:
• 不使用 prefetch_related 的情况下,查询时间会随着作者数量的增加而线性增长。
• 使用 prefetch_related 后,查询时间基本保持不变,因为关联数据的查询次数大大减少。

注意事项

  1. 适用场景prefetch_related 主要用于处理“多对多”和“一对多”关系。对于“一对一”或“外键”关系,通常使用 select_related 更为高效。

  2. 内存消耗:由于 prefetch_related 会将所有预取的数据加载到内存中,如果关联数据量非常大,可能会导致内存占用过高。因此,在处理大数据集时需要谨慎使用。

  3. 自定义查询:通过 Prefetch 对象,可以自定义预取的查询集,如过滤、排序或限制数量,从而进一步优化性能。

  4. 链式调用prefetch_related 可以与其他查询优化方法(如 filterexclude 等)结合使用,以满足复杂的查询需求。

总结

prefetch_related 是 Django ORM 提供的一个强大的查询优化工具,特别适用于处理多对多和一对多关系中的 N+1 查询问题。通过预先加载关联对象,prefetch_related 能够显著减少数据库查询次数,提高应用的性能。在使用时,需要根据具体的业务场景选择合适的预取策略,并注意内存消耗等问题,以达到最佳的优化效果。

希望通过以上的解释和示例,你对 django-prefetch_related 有了更深入的理解!

Django-ORM-prefetch_related

  • 模型定义
    • N+1 查询问题示例
  • 使用 prefetch_related 优化查询
  • 处理更复杂的查询
    • 示例:预取特定条件的书籍
    • 示例:预取多个关联字段
  • 性能比较
  • 注意事项
  • 总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/33892.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UE5以插件的形式加载第三方库

之前在UE中加载第三方库的形式是以静态或者动态链接的形式加载但是不太容易复用。就想着能不能以插件的形式加载第三方库,这样直接把插件打包发行就可以复用了,之前也找过相应的教程但是很难找到比较简单易懂的教程,要么是比较复杂&#xff0…

Go执行当前package下的所有方法

需求:需要一个文件一个定时任务方法,当项目初始化完毕后,自动加载并执行这些定时任务方法 项目目录架构 main.go 初始化 package mainimport ("sql_demo/schedule" )func main() {/***** 其他初始化完毕后的操作**/// 定时任务sc…

AnyAnomaly: 基于大型视觉语言模型的零样本可定制视频异常检测

文章目录 速览摘要1. 引言2. 相关工作视频异常检测大型视觉语言模型(LVLMs) 3. 方法3.1. 总览3.2. 关键帧选择模块3.3. 上下文生成基于 WinCLIP 的注意力机制网格图像生成 3.4. 异常检测提示词设计异常评分 4. 实验4.1. 数据集4.2. 评估标准4.3. 结果4.4…

【AWS入门】2025 AWS亚马逊云科技账户注册指南

【AWS入门】2025 AWS亚马逊云科技账户注册指南 A Guide To Register a New account on AWS By JacksonML 0. AWS亚马逊云科技简介 Amazon Web Service(AWS) 即亚马逊云科技,其在全球Cloud Computing(云计算)市场占有最为重要的地位。 AWS连续13年被Gartner评为…

Spring 中 SmartInitializingSingleton 的作用和示例

一、 接口定义 SmartInitializingSingleton 是 Spring 框架提供的一个 单例 Bean 全局初始化回调接口,用于在 所有非延迟单例 Bean 初始化完成后 执行自定义逻辑。 核心方法: public interface SmartInitializingSingleton {void afterSingletonsInsta…

element tree树形结构默认展开全部

背景: el-tree树形结构,默认展开全部,使用属性default-expand-all【是否默认展开所有节点】;默认展开一级,设置default-expanded-keys【默认展开的节点的 key 的数组】属性值为数组。 因为我这里的数据第一级是四川【省…

大数据-spark3.5安装部署之local模式

spark,一个数据处理框架和计算引擎。 下载 local模式即本地模式,就是不需要任何其他节点资源就可以在本地执行spark代码的环境。用于练习演示。 上传解压 使用PortX将文件上传至/opt 进入/opt目录,创建目录module,解压文件至/o…

Discuz建站教程之论坛头部logo跳转链接怎么修改?

在修改头部logo跳转链接前&#xff0c;我们需要知道对应代码在哪个文件目录&#xff0c;进入宝塔或是服务器&#xff0c;找到文件&#xff1a;\template\default\common\header.htm&#xff0c;编辑器打开&#xff0c;搜索以下代码&#xff0c;大概在135行 <a href"{i…

【FreeRTOS】FreeRTOS操作系统在嵌入式单片机上裸机移植

目录 一 RTOS概述 二 FreeRTOS移植 三 FreeRTOS使用 四 附录 一 RTOS概述 先了解一些基础概念,以下内容摘自FreeRTOS官网(FreeRTOS™ - FreeRTOS™): 【1】RTOS基础知识 实时操作系统 (RTOS) 是一种体积小巧、确定性强的计算机操作系统。 RTOS 通常用于需要在严格时间限…

编译支持 RKmpp 和 RGA 的 ffmpeg 源码

一、前言 RK3588 支持VPU硬件解码&#xff0c;需要rkmpp进行调用&#xff1b;支持2D图像加速&#xff0c;需要 RGA 进行调用。 这两个库均能通过 ffmpeg-rockchip 进行间接调用&#xff0c;编译时需要开启对应的功能。 二、依赖安装 编译ffmpeg前需要编译 rkmpp 和 RGA&#xf…

深度学习基础:线性代数本质2——线性组合、张成的空间与基

目录 一、线性组合 1. 用一个有趣的角度看向量坐标 2. 如果我们选择不同的基向量会怎样&#xff1f; 3. 线性组合 4. 张成的空间 ① 二维向量的张成的空间 ② 三维向量的张成的空间​编辑 5.线性相关 6.线性无关 7. 基的定义 一、线性组合 1. 用一个有趣的角度看向量坐…

openharmony5.0中HDF驱动框架源码梳理-服务管理接口

要想大概了解一个公司&#xff0c;我们可能只需要知道它的运行逻辑即可&#xff0c;例如我们只需要知道它有财务有研发有运营等&#xff0c;财务报销、研发负责产品等即可&#xff0c;但是如果想深入具体的了解的话我们就要了解都有什么部门(对象)、各部门都包含哪些职责(对象方…

Go语言环境搭建并执行第一个Go程序

目录 一、Windows环境搭建 二、vscode安装插件 三、运行第一个go程序 一、Windows环境搭建 下载Go&#xff1a;All releases - The Go Programming Language 这里是Windows搭建&#xff0c;选择的是windows-amd64.msi&#xff0c;也可以选择zip直接解压缩到指定目录 选择msi…

Netty基础—4.NIO的使用简介一

大纲 1.Buffer缓冲区 2.Channel通道 3.BIO编程 4.伪异步IO编程 5.改造程序以支持长连接 6.NIO三大核心组件 7.NIO服务端的创建流程 8.NIO客户端的创建流程 9.NIO优点总结 10.NIO问题总结 1.Buffer缓冲区 (1)Buffer缓冲区的作用 (2)Buffer缓冲区的4个核心概念 (3)使…

linux 命令 tail

tail 是 Linux 中用于查看文件末尾内容的命令&#xff0c;常用于日志监控和大文件快速浏览。以下是其核心用法及常见选项&#xff1a; 基本语法 tail [选项] 文件名 常用选项 显示末尾行数 -n <行数> 或 --lines<行数> 指定显示文件的最后若干行&#xff08;…

网络华为HCIA+HCIP数据链路层协议-以太网协议

以太网协议 以太网是当今现有局域网(Local Area Network,LAN)采用的最通用的通信协议标准&#xff0c;该标准定义了在局域网中采用的电缆类型和信号处理方法。以太网是建立在CSMA/CD(Carrier Sense Multiple Access/Collision Detection,载波监听多路访问/冲突检测)机制上的广…

缓存id路由页面返回,历史路由栈

功能需求 网页端需要做页面数据缓存&#xff08;vue动态路由数据缓存&#xff09;&#xff0c;可根据id值打开多个编辑详情页&#xff0c;需要在页面操作返回时关闭面包屑页签 隐藏问题 1.页面缓存会有初始化和组件激活访问生命周期调用数据接口过多&#xff0c;有性能损耗 2.使…

mingw工具源码编译

ming-w64 mingw编译生成的库&#xff0c;需要mingw的lib文件支持。 https://github.com/mingw-w64/mingw-w64 使用msys2的bash git checkout v8.0.3 ./configure --disable-dependency-tracking --targetx86_64-w64-mingw32 mingw32-make.exe -j4 修改makefile中的make 改成mi…

使用OpenCV和MediaPipe库——抽烟检测(姿态监控)

目录 抽烟检测的运用 1. 安全监控 (1) 公共场所禁烟监管 (2) 工业安全 2. 智能城市与执法 (1) 城市违章吸烟检测 (2) 无人值守管理 3. 健康管理与医疗 (1) 吸烟习惯分析 (2) 远程监护 4. AI 监控与商业分析 (1) 保险行业 (2) 商场营销 5. 技术实现 (1) 计算机视…

大数据学习(66)- CDH管理平台

&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一…