首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Django链接prefetch_related和select_related

prefetch_relatedselect_related是Django ORM中用于优化查询性能的两个重要方法。它们都可以减少数据库查询的次数,从而提高应用程序的性能。

基础概念

  1. select_related:
    • 用于单对一关系(OneToOneField)和外键关系(ForeignKey)。
    • 它会在执行查询时立即获取相关对象,通过SQL JOIN操作将相关对象的数据一并检索出来。
    • 结果是返回一个QuerySet,其中每个对象都包含了其关联对象的数据。
  • prefetch_related:
    • 用于多对多关系(ManyToManyField)和反向外键关系。
    • 它不会立即获取相关对象,而是在Python层面上进行连接。
    • 它会先获取主对象的QuerySet,然后在Python中遍历这个QuerySet,对每个对象分别进行一次数据库查询来获取其关联对象。

优势

  • 减少数据库查询次数: 这两个方法都能显著减少数据库查询的次数,特别是在处理大量数据时。
  • 提高性能: 通过减少数据库交互,可以提高应用程序的响应速度和整体性能。

类型

  • select_related: 适用于一对一和外键关系。
  • prefetch_related: 适用于多对多和反向外键关系。

应用场景

  • 当你需要频繁访问关联对象的数据时,使用select_related可以减少查询次数。
  • 当关联对象的数据量很大,或者关联关系复杂时,使用prefetch_related可以在Python层面上更高效地处理这些数据。

示例代码

假设我们有两个模型,AuthorBook,其中Author有一个外键指向Book

代码语言:txt
复制
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

使用select_related

代码语言:txt
复制
# 获取所有书籍及其作者信息,只进行一次数据库查询
books = Book.objects.select_related('author')
for book in books:
    print(book.title, book.author.name)

使用prefetch_related

代码语言:txt
复制
# 假设我们有一个多对多的关系,Author和Genre
class Genre(models.Model):
    name = models.CharField(max_length=100)

class Author(models.Model):
    name = models.CharField(max_length=100)
    genres = models.ManyToManyField(Genre)

# 获取所有作者及其喜欢的类型,进行两次数据库查询
authors = Author.objects.prefetch_related('genres')
for author in authors:
    print(author.name, [genre.name for genre in author.genres.all()])

遇到的问题及解决方法

问题:使用select_related后,为什么关联对象的数据没有更新?

原因: select_related在查询时就已经确定了关联对象的数据,所以如果你在之后修改了关联对象的数据,这些更改不会反映在使用select_related获取的对象上。

解决方法: 使用refresh_from_db()方法来重新从数据库加载对象的数据。

代码语言:txt
复制
book.author.name = "New Author Name"
book.author.save()
book.author.refresh_from_db()  # 重新加载author对象的数据

问题:使用prefetch_related后,为什么查询结果不正确?

原因: prefetch_related在Python层面上进行连接,如果你的查询条件涉及到关联对象,可能会导致查询结果不正确。

解决方法: 确保你的查询条件正确地应用在主对象上,或者使用Prefetch对象来自定义预取的行为。

代码语言:txt
复制
from django.db.models import Prefetch

books = Book.objects.prefetch_related(
    Prefetch('author', queryset=Author.objects.filter(name__startswith='A'))
)

通过这些方法,你可以有效地使用select_relatedprefetch_related来优化你的Django应用程序的性能。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

django select_related和prefetch_related的用法与区别

今天我们再来学习两个非常重要的查询方法select_related和prefetch_related方法,看看如何使用它们避免不必要的数据库查询。高手过招,只差分毫。...我们先分析下这会什么会发生,然后再解释如何使用select_related和prefetch_related方法解决这个问题。 为什么会有重复查询?...Django考虑到了这一点,所以提供select_related和prefetch_related方法来提升数据库查询效率,类似于SQL的JOIN方法。...和prefetch_related一次性获取所有对象信息,从而提升数据库查询效率,避免重复查询。...对与单对单或单对多外键ForeignKey字段,使用select_related方法 对于多对多字段和反向外键关系,使用prefetch_related方法 两种方法均支持双下划线指定需要查询的关联对象的字段名

1.4K20
  • Django ORM:天使与魔鬼 II

    在 Django 中我们通常会使用 selected_related 或prefetch_related 来预取关联对象,来减少和 DB 之间的交互,但是在使用上也需要有一些注意的地方。...() ,默认地 Django 会将所有关联字段都取出来,加入 Baz 表无比巨大,本来用作性能优化的 prefetch_related 就会摇身变成耗时怪兽。...此时在后续的循环处理中,我们需要通过 Foo 对象查询到 Baz 的数据,为了避免 N + 1 我们也会多级预取: Foo.objects.filter().select_related("bars")...Foo.objects.filter().select_related("bars") .prefetch_related( Prefetch("bars__bazs", queryset=Baz.objects.defer...https://github.com/TencentBlueKing/python-best-practices 我和团队小伙伴整理了很多 Python\Django\DRF 的最佳实践经验,项目会持续更新

    72850

    Django进阶-9-ORM分组与聚合查询

    models.Articles.objects.all() for row in obj_list: print(row.name) 这种查询方式第一次发送 查询请求每for循环一次也会发送查询请求 ② select_related...查询时主动完成连表形成一张大表,for循环时不用额外发请求; 试用场景: 节省硬盘空间,数据量少时候适用相当于做了一次数据库查询; obj_list=models.Articles.objects.all().select_related...,所以出现prefetch_related; prefetch_related:不做连表,多次单表查询外键表 ,去重之后显示, 2次单表查询(有几个外键做几次1+N次单表查询) 适用场景:效率高,数据量大的时候适用...print(obj.category.name) 二、ORM 分组和聚合查询 ① aggregate(*args,**kwargs) 聚合函数 通过对 QuerySet 进行计算,返回一个聚合值的字典...from django.db.models import Avg,Sum,Max,Min #求书籍的平均价 ret=models.Book.objects.all().aggregate(Avg('price

    1K20

    提高Djang查询速度的9种方法

    优化数据库查询可以显著提高应用程序的性能和响应速度。Django作为一个高度可扩展的Web框架,提供了多种方式来优化数据库查询。...目录索引的优化查询集的延迟加载使用select_related进行关联查询使用prefetch_related进行预取延迟计算字段使用values()和values_list()方法选择需要的字段使用annotate...使用select_related进行关联查询在涉及到关联表的查询中,使用select_related()方法可以减少数据库查询的次数。...select_related()方法会在查询时一次性将相关的对象也查询出来,而不是每次访问关联对象时都执行一次查询。例如,我们有一个Book模型和一个Author模型,它们之间存在一对多关系。...使用prefetch_related进行预取在进行跨关联的查询时,使用prefetch_related()方法可以有效地减少数据库查询次数。

    31520

    Django学习笔记之Queryset详解

    对于onetomany的反向和manytomany,要用prefetch_related,它返回的是多条关联记录,是QuerySet。...其实,prefetch_related()也能做select_related()的事情,但由于策略不同,可能相比select_related()要低效一些,所以建议还是各管各擅长的。...select_related是用select ……join来返回关联的表字段,而prefetch_related是用多条SQL语句的形式查询,一般,后一条语句用IN来调用上一句话返回的结果。...('best_pizza__toppings') 先用select_related查到best_pizza对象,再用prefetch_related 从best_pizza查出toppings 2.4.9...()和prefetch_related(),可以是任意深度(即任意多个双下划线)的关联,通常一层关联和二层关联用的比较多;第三种:返回ValuesQuerySet, ValuesListQuerySet

    2.7K30

    Django-model进阶(中介模型,查询优化,extra,整体插入)

    下面的例子解释了普通查询和select_related() 查询的区别。...如果要访问指定深度外的字段,Django会再次进行SQL查询。 也接受无参数的调用,Django会尽可能深的递归查询所有的字段。但注意有Django递归的限制和性能的浪费。...Django >= 1.7,链式调用的select_related相当于使用可变长参数。Django select_related失效,只保留最后一个。...prefetch_related() 对于多对多字段(ManyToManyField)和一对多字段,可以使用prefetch_related()来进行优化。...prefetch_related()和select_related()的设计目的很相似,都是为了减少SQL查询的数量,但是实现的方式不一样。后者是通过JOIN语句,在SQL查询内解决问题。

    1.6K70

    提升Django性能数据库优化与ORM调优技巧详解

    和prefetch_related 在处理关联查询时,使用select_related和prefetch_related可以减少数据库查询次数,提高性能。...).get(pk=1) # 使用prefetch_related authors = Author.objects.prefetch_related('books') 4....# 使用Django的dumpdata和loaddata命令进行数据库备份和恢复 # 备份数据库 python manage.py dumpdata > backup.json # 恢复数据库 python...使用缓存服务 除了Django内置的缓存机制外,还可以使用专门的缓存服务如Redis来提高数据访问速度和降低数据库负载。Redis支持更复杂的数据结构和操作,能够更灵活地应对各种场景。...结语 数据库优化和ORM性能调优是提升Django应用程序性能和稳定性的关键步骤。

    34020

    【Django】Django ORM 学习笔记

    对象和关系之间并不是完美映射 一般来说 ORM 足以满足我们的需求,如果对性能要求特别高或者查询十分复杂,可以考虑使用原生 SQL 和 ORM 共用的方式 Django ORM 在 Django 框架中集成了...ORM 中的关联查询也分两中 select_related(单关联实例) 和 prefetch_related(多关联实例) select_related select_related 用来处理单关联实例的情况...如果需要清除 QuerySet 上以前的 select_related 添加的关联字段,可以传入 None 做参数 prefetch_related prefetch_related 主要适用于 OneTwoMany...和 select_related 类似,prefetch_related 在查询时会同时取出关联实例的值。...与 select_related 不同的是 prefetch_related 不使用 JOIN 方式来查询数据库,而是分别查每个表,最后使用 Python 来实现 JOIN 操作。

    2.2K20

    Django数据库查询优化与AJAX

    与prefetch_related select_related 括号内只能放一对一、一对多的外键字段,特点:内部自动连表操作,会将括号内外键字段所关联的表与当前表自动拼接成一张表,然后将表中的数据一个一个查询出来封装成一个一个的对象...select_related()括号内放多个外键字段,逗号隔开,会将多个外键字段关联的表与当前表拼成一张大表。...耗时:数据库层面连表操作,当数据库特别大时可能连表的时间会长一点,用prefetch_related可能会好一点,但如果表比较小两者基本没太大差别。...prefetch_related内部是子查询(当一个查询是另一个查询的条件时,称之为子查询。)...stringfy和parse方法 JavaScript中关于JSON对象和字符串转换的两个方法: JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象(json只认双引的字符串格式

    2.4K20
    领券