优化Django中的数据库查询次数很关键,这样可以提高性能,确保应用程序能高效处理高流量。这里有一些减少和优化数据库查询次数的策略。
1. 使用Select Related和Prefetch Related**select_related**
:适用于一对一关系(ForeignKey, OneToOne)。它通过执行 SQL 连接并在 SELECT 语句中包含相关对象的字段来减少查询次数。
# 获取书及其作者的单个查询
books = Book.objects.select_related('author').all()
**prefetch_related**
:用于这种情况(多对多关系及反向 ForeignKey)。它会分别执行查询,然后在Python中进行关联。
# 分别查询书籍及其标签,然后在Python里合并
books = Book.objects.prefetch_related('tags').all()
2. 要避免 N+1 查询问题
当你对列表中的每个项目都进行查询时,会产生许多额外的查询,这就是N+1查询问题。可以通过使用select_related
和prefetch_related
来避免这种情况。
Django的查询集是惰性的,只有在被评估时才会访问数据库。如果你想多次使用这些结果,可以将它们存储在变量中。
books = Book.objects.all() # QuerySet
for book in books:
# 处理这本书
# 对每一本书进行处理
4. 使用这两个方法 .only()
和 .defer()
。
- 仅: 只获取字段子集,以减少获取的数据。
books = Book.objects.only('title', 'author') # 只获取书籍的标题和作者信息
**推迟加载**
:只加载除了指定字段以外的其他所有字段,这在你需要大部分字段但不是所有字段时很有用。
# 省略了 'long_description' 字段
books = Book.objects.defer('long_description')
5. 使用索引
确保用于查找或排序的数据库字段已经被正确索引。您可以在模型定义中添加索引。
# 定义一个Book类,继承models.Model
class Book(models.Model):
# 书名,最大长度为200个字符,且在数据库中建立索引
title = models.CharField(max_length=200, db_index=True)
# 作者,与Author模型相关联,删除作者时删除相关书籍
author = models.ForeignKey(Author, on_delete=models.CASCADE)
6. 优化QuerySets
- 尽早过滤:尽早开始过滤,这样可以减少处理的数据量。
books = Book.objects.filter(published=True).select_related('author')
这行代码的意思是从Book模型中筛选出已发布的书籍,并且关联了作者的信息。
- Pagination : 对于大型数据集,建议使用分页功能以避免一次性加载所有记录,而是分批次加载。
from django.core.paginator import Paginator
books = Book.objects.all()
paginator = Paginator(books, 10) # 每页显示10本
page_number = 1 # 设定当前页为第1页
page_obj = paginator.get_page(page_number)
7. 使用原生 SQL 进行复杂的查询
在这种情况下,对于非常复杂的查询或性能关键的任务,您可以使用原生SQL。需注意防范SQL注入等安全问题。
# 导入 django.db 中的 connection
with connection.cursor() as cursor: # 使用 connection.cursor() 作为游标
cursor.execute("SELECT * FROM myapp_book WHERE published=%s", [True]) # 查询已发布的书籍
rows = cursor.fetchall() # 获取所有行
第8点 优化你的数据库架构
- 避免使用不必要的字段:只保留你需要的数据。
- 数据规范化:确保你的数据模式已规范化以减少冗余。
使用Django的debug工具栏功能,SILK 或日志来分析查询性能并找出优化点,以识别需要优化的部分。
10. 使用批量创建和批量更新批量创建:.bulk_create
批量更新:.bulk_update
- 批量插入: 当你需要一次插入大量记录时,使用 Django 的
bulk_create()
方法比单独插入每条记录要高效得多。这可以减少发送到数据库的查询次数
# 假设你有一个要创建的图书列表
books = [
Book(title='书 1', author=author1),
Book(title='书 2', author=author2),
# 添加更多书籍
]
# 执行批量创建动作
Book.objects.bulk_create(books)
- 批量更新记录:同样,也可以使用
bulk_update()
来高效更新多条记录。这在需要更新多条记录为新值时非常有用。
# 假设你有一系列需要更新字段的 Book 对象
books = [
Book(id=1, title='标题1 更新后'),
Book(id=2, title='标题2 更新后'),
# 添加更多需要更新的 Book 实例
]
# 执行批量更新
Book.objects.bulk_update(books, ['title'])
结论部分
这些方法在处理大量数据时可以显著提升性能,所以在性能很重要的情况下,绝对值得一试。
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦