django之select_related 与 prefetch_related用法

打印 上一主题 下一主题

主题 537|帖子 537|积分 1611

在 Django 中,select_related 和 prefetch_related 是用于优化查询的两个紧张方法。它们通过淘汰数据库查询次数来提高性能,但它们的工作方式有所不同。
select_related

select_related 使用 SQL 的 JOIN 操纵来获取相关对象。它实用于一对一和多对一的关系(如 ForeignKey 和 OneToOneField)。它会在单个查询中获取相关对象的数据,从而淘汰数据库查询次数。
示例

假设我们有以下模型:
  1. from django.db import models
  2. class Author(models.Model):
  3.     name = models.CharField(max_length=100)
  4.     email = models.EmailField()
  5.     def __str__(self):
  6.         return self.name
  7. class Book(models.Model):
  8.     title = models.CharField(max_length=200)
  9.     publication_date = models.DateField()
  10.     author = models.ForeignKey(Author, related_name='books', on_delete=models.CASCADE)
  11.     def __str__(self):
  12.         return self.title
复制代码
可以使用 select_related 来优化查询:
  1. # 获取所有书籍及其对应的作者
  2. books = Book.objects.select_related('author').all()
  3. for book in books:
  4.     print(f"{book.title} by {book.author.name}")
复制代码
在这个示例中,select_related('author') 会在单个查询中获取所有册本及其对应的作者,从而制止了每次访问 book.author 时的额外查询。
prefetch_related

prefetch_related 使用单独的查询来获取相关对象,然后在 Python 中进行关联。它实用于一对多和多对多的关系(如 ForeignKey、OneToOneField 和 ManyToManyField)。它会在单独的查询中获取相关对象的数据,然后在内存中进行关联。
示例

假设我们有以下模型:
  1. from django.db import models
  2. class Author(models.Model):
  3.     name = models.CharField(max_length=100)
  4.     email = models.EmailField()
  5.     def __str__(self):
  6.         return self.name
  7. class Book(models.Model):
  8.     title = models.CharField(max_length=200)
  9.     publication_date = models.DateField()
  10.     author = models.ForeignKey(Author, related_name='books', on_delete=models.CASCADE)
  11.     def __str__(self):
  12.         return self.title
复制代码
可以使用 prefetch_related 来优化查询:
  1. # 获取所有作者及其对应的书籍
  2. authors = Author.objects.prefetch_related('books').all()
  3. for author in authors:
  4.     print(f"Books by {author.name}:")
  5.     for book in author.books.all():
  6.         print(f" - {book.title}")
复制代码
在这个示例中,prefetch_related('books') 会在单独的查询中获取所有作者及其对应的册本,然后在内存中进行关联,从而制止了每次访问 author.books.all() 时的额外查询。
选择 select_related 照旧 prefetch_related



  • select_related实用于一对一和多对一的关系。它使用 SQL JOIN 操纵,在单个查询中获取相关对象的数据。
  • prefetch_related实用于一对多和多对多的关系。它使用单独的查询来获取相关对象的数据,然后在内存中进行关联。
组合使用

在某些情况下,可能需要同时使用 select_related 和 prefetch_related 来优化查询。
示例

假设我们有以下模型:
  1. from django.db import models
  2. class Publisher(models.Model):
  3.     name = models.CharField(max_length=100)
  4.     def __str__(self):
  5.         return self.name
  6. class Author(models.Model):
  7.     name = models.CharField(max_length=100)
  8.     email = models.EmailField()
  9.     publisher = models.ForeignKey(Publisher, related_name='authors', on_delete=models.CASCADE)
  10.     def __str__(self):
  11.         return self.name
  12. class Book(models.Model):
  13.     title = models.CharField(max_length=200)
  14.     publication_date = models.DateField()
  15.     author = models.ForeignKey(Author, related_name='books', on_delete=models.CASCADE)
  16.     def __str__(self):
  17.         return self.title
复制代码
可以同时使用 select_related 和 prefetch_related 来优化查询:
  1. # 获取所有书籍及其对应的作者和出版社
  2. books = Book.objects.select_related('author__publisher').prefetch_related('author__books').all()
  3. for book in books:
  4.     print(f"{book.title} by {book.author.name} (Publisher: {book.author.publisher.name})")
  5.     print("Other books by this author:")
  6.     for other_book in book.author.books.all():
  7.         if other_book != book:
  8.             print(f" - {other_book.title}")
复制代码
在这个示例中,select_related('author__publisher') 会在单个查询中获取册本、作者及其对应的出版社,而 prefetch_related('author__books') 会在单独的查询中获取作者及其对应的册本,然后在内存中进行关联。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

天空闲话

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表