一、基础批量查询方法
1. 批量获取对象列表
# 获取所有电影对象(避免内存溢出)
films = film.objects.all()
# 使用迭代器处理大规模数据
for film in films.iterator(chunk_size=1000):
# 处理每个电影对象
print(film.title)
2. 按条件批量筛选
# 获取2023年上映的电影 films_2023 = film.objects.filter(year=2023) # 获取评分大于4.0的电影 high_rated_films = film.objects.filter(rating__gt=4.0)
3. 批量值查询(减少内存占用)
# 只获取需要的字段
film_titles = film.objects.values_list('title', flat=true)
# 获取特定字段组合
film_data = film.objects.values('id', 'title', 'year')
二、高级批量查询技术
1. 批量关联查询优化
# 使用select_related优化外键查询
films = film.objects.select_related('studio').all()
# 使用prefetch_related优化多对多关系
films = film.objects.prefetch_related('actors').all()
2. 批量id查询
# 获取特定id集合的电影 film_ids = [101, 205, 307, 409] films = film.objects.in_bulk(film_ids, field_name='id') # 使用结果 film_205 = films[205]
3. 批量分页查询
from django.core.paginator import paginator
# 每页100条记录
paginator = paginator(film.objects.all(), 100)
for page_num in range(1, paginator.num_pages + 1):
page = paginator.page(page_num)
for film in page.object_list:
# 处理每部电影
process_film(film)
三、批量操作api
1. 批量创建
# 创建多个电影对象
films_to_create = [
film(title="电影a", year=2023),
film(title="电影b", year=2022),
film(title="电影c", year=2021)
]
# 批量创建(返回创建的对象列表)
created_films = film.objects.bulk_create(films_to_create)
2. 批量更新
# 批量更新评分
films_to_update = film.objects.filter(year=2023)
for film in films_to_update:
film.rating = 4.5 # 更新评分
# 批量更新到数据库
film.objects.bulk_update(films_to_update, ['rating'])
3. 批量删除
# 删除所有2020年之前的电影 film.objects.filter(year__lt=2020).delete()
四、性能优化技巧
1. 使用only()和defer()减少字段加载
# 只加载必要字段
films = film.objects.only('title', 'year')
# 排除大字段
films = film.objects.defer('plot')
2. 批量处理关联对象
# 批量添加演员 film = film.objects.get(id=101) actors_to_add = actor.objects.filter(id__in=[1, 2, 3]) film.actors.add(*actors_to_add) # 批量移除演员 film.actors.remove(*actors_to_add)
3. 使用原生sql进行复杂批量操作
from django.db import connection
def bulk_update_ratings():
with connection.cursor() as cursor:
cursor.execute("""
update film_information
set rating = rating * 1.1
where year >= 2020
""")
五、实战场景示例
1. 批量更新电影评分
def update_film_ratings():
# 获取需要更新的电影
films = film.objects.filter(year__gte=2020)
# 批量更新评分
for film in films:
film.rating = calculate_new_rating(film)
# 批量提交到数据库
film.objects.bulk_update(films, ['rating'], batch_size=500)
2. 批量导入电影数据
def import_films_from_csv(csv_path):
import csv
films_to_create = []
with open(csv_path, 'r', encoding='utf-8') as f:
reader = csv.dictreader(f)
for row in reader:
films_to_create.append(film(
title=row['title'],
year=int(row['year']),
# ...其他字段
))
# 分批次创建(每批1000条)
batch_size = 1000
for i in range(0, len(films_to_create), batch_size):
batch = films_to_create[i:i+batch_size]
film.objects.bulk_create(batch)
3. 批量处理电影标签
def process_film_tags():
# 获取所有电影及其标签
films = film.objects.prefetch_related('tags')
for film in films:
# 处理每个电影的标签
tags_to_add = calculate_new_tags(film)
film.tags.add(*tags_to_add)
# 移除不需要的标签
tags_to_remove = get_obsolete_tags(film)
film.tags.remove(*tags_to_remove)
六、性能对比
| 方法 | 10,000条记录耗时 | 内存占用 | 适用场景 |
|---|---|---|---|
| 普通循环 | 15.2s | 高 | 小数据集 |
| bulk_create | 1.8s | 中 | 批量创建 |
| bulk_update | 2.1s | 中 | 批量更新 |
| 原生sql | 0.3s | 低 | 超大规模数据 |
| 分页处理 | 8.5s | 低 | 内存敏感场景 |
七、最佳实践建议
选择合适的批量大小:
- 推荐
batch_size=500-1000 - 根据数据库性能调整
事务管理:
from django.db import transaction
with transaction.atomic():
# 批量操作代码
film.objects.bulk_create(films)
错误处理:
try:
film.objects.bulk_update(films, ['rating'])
except exception as e:
logger.error(f"批量更新失败: {str(e)}")
# 回退或重试逻辑
性能监控:
from django.db import connection print(connection.queries) # 查看执行的sql查询
总结
django 提供了多种批量查询和处理方法:
- 查询优化:
select_related,prefetch_related,values() - 批量操作:
bulk_create,bulk_update,in_bulk - 内存管理:
iterator(),paginator - 高级技巧:原生sql、事务管理
通过合理使用这些技术,可以将处理10万条记录的时间从分钟级降低到秒级,同时显著减少内存占用。关键是根据具体场景选择最合适的批量处理方法,并注意错误处理和性能监控。
以上就是django批量查询优化的多种实现方案的详细内容,更多关于django批量查询优化的资料请关注代码网其它相关文章!
发表评论