一、基础批量查询方法
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批量查询优化的资料请关注代码网其它相关文章!
发表评论