Django批量查詢優(yōu)化的多種實(shí)現(xiàn)方案
一、基礎(chǔ)批量查詢方法
1. 批量獲取對(duì)象列表
# 獲取所有電影對(duì)象(避免內(nèi)存溢出)
films = Film.objects.all()
# 使用迭代器處理大規(guī)模數(shù)據(jù)
for film in films.iterator(chunk_size=1000):
# 處理每個(gè)電影對(duì)象
print(film.title)
2. 按條件批量篩選
# 獲取2023年上映的電影 films_2023 = Film.objects.filter(year=2023) # 獲取評(píng)分大于4.0的電影 high_rated_films = Film.objects.filter(rating__gt=4.0)
3. 批量值查詢(減少內(nèi)存占用)
# 只獲取需要的字段
film_titles = Film.objects.values_list('title', flat=True)
# 獲取特定字段組合
film_data = Film.objects.values('id', 'title', 'year')
二、高級(jí)批量查詢技術(shù)
1. 批量關(guān)聯(lián)查詢優(yōu)化
# 使用select_related優(yōu)化外鍵查詢
films = Film.objects.select_related('studio').all()
# 使用prefetch_related優(yōu)化多對(duì)多關(guān)系
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') # 使用結(jié)果 film_205 = films[205]
3. 批量分頁(yè)查詢
from django.core.paginator import Paginator
# 每頁(yè)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. 批量創(chuàng)建
# 創(chuàng)建多個(gè)電影對(duì)象
films_to_create = [
Film(title="電影A", year=2023),
Film(title="電影B", year=2022),
Film(title="電影C", year=2021)
]
# 批量創(chuàng)建(返回創(chuàng)建的對(duì)象列表)
created_films = Film.objects.bulk_create(films_to_create)
2. 批量更新
# 批量更新評(píng)分
films_to_update = Film.objects.filter(year=2023)
for film in films_to_update:
film.rating = 4.5 # 更新評(píng)分
# 批量更新到數(shù)據(jù)庫(kù)
Film.objects.bulk_update(films_to_update, ['rating'])
3. 批量刪除
# 刪除所有2020年之前的電影 Film.objects.filter(year__lt=2020).delete()
四、性能優(yōu)化技巧
1. 使用only()和defer()減少字段加載
# 只加載必要字段
films = Film.objects.only('title', 'year')
# 排除大字段
films = Film.objects.defer('plot')
2. 批量處理關(guān)聯(lián)對(duì)象
# 批量添加演員 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進(jìn)行復(fù)雜批量操作
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
""")
五、實(shí)戰(zhàn)場(chǎng)景示例
1. 批量更新電影評(píng)分
def update_film_ratings():
# 獲取需要更新的電影
films = Film.objects.filter(year__gte=2020)
# 批量更新評(píng)分
for film in films:
film.rating = calculate_new_rating(film)
# 批量提交到數(shù)據(jù)庫(kù)
Film.objects.bulk_update(films, ['rating'], batch_size=500)
2. 批量導(dǎo)入電影數(shù)據(jù)
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']),
# ...其他字段
))
# 分批次創(chuàng)建(每批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. 批量處理電影標(biāo)簽
def process_film_tags():
# 獲取所有電影及其標(biāo)簽
films = Film.objects.prefetch_related('tags')
for film in films:
# 處理每個(gè)電影的標(biāo)簽
tags_to_add = calculate_new_tags(film)
film.tags.add(*tags_to_add)
# 移除不需要的標(biāo)簽
tags_to_remove = get_obsolete_tags(film)
film.tags.remove(*tags_to_remove)
六、性能對(duì)比
| 方法 | 10,000條記錄耗時(shí) | 內(nèi)存占用 | 適用場(chǎng)景 |
|---|---|---|---|
| 普通循環(huán) | 15.2s | 高 | 小數(shù)據(jù)集 |
| bulk_create | 1.8s | 中 | 批量創(chuàng)建 |
| bulk_update | 2.1s | 中 | 批量更新 |
| 原生SQL | 0.3s | 低 | 超大規(guī)模數(shù)據(jù) |
| 分頁(yè)處理 | 8.5s | 低 | 內(nèi)存敏感場(chǎng)景 |
七、最佳實(shí)踐建議
選擇合適的批量大小:
- 推薦
batch_size=500-1000 - 根據(jù)數(shù)據(jù)庫(kù)性能調(diào)整
事務(wù)管理:
from django.db import transaction
with transaction.atomic():
# 批量操作代碼
Film.objects.bulk_create(films)
錯(cuò)誤處理:
try:
Film.objects.bulk_update(films, ['rating'])
except Exception as e:
logger.error(f"批量更新失敗: {str(e)}")
# 回退或重試邏輯
性能監(jiān)控:
from django.db import connection print(connection.queries) # 查看執(zhí)行的SQL查詢
總結(jié)
Django 提供了多種批量查詢和處理方法:
- 查詢優(yōu)化:
select_related,prefetch_related,values() - 批量操作:
bulk_create,bulk_update,in_bulk - 內(nèi)存管理:
iterator(),Paginator - 高級(jí)技巧:原生SQL、事務(wù)管理
通過(guò)合理使用這些技術(shù),可以將處理10萬(wàn)條記錄的時(shí)間從分鐘級(jí)降低到秒級(jí),同時(shí)顯著減少內(nèi)存占用。關(guān)鍵是根據(jù)具體場(chǎng)景選擇最合適的批量處理方法,并注意錯(cuò)誤處理和性能監(jiān)控。
以上就是Django批量查詢優(yōu)化的多種實(shí)現(xiàn)方案的詳細(xì)內(nèi)容,更多關(guān)于Django批量查詢優(yōu)化的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python?EasyDict庫(kù)以屬性方式訪問(wèn)字典元素(無(wú)需使用方括號(hào)和鍵)
在Python中,字典(dict)是一種常用的數(shù)據(jù)結(jié)構(gòu),用于存儲(chǔ)鍵值對(duì),然而,有時(shí)候我們希望以屬性的方式訪問(wèn)字典中的元素,而無(wú)需使用方括號(hào)和鍵,這就是EasyDict庫(kù)的用武之地,本文將深入介紹EasyDict庫(kù),展示其強(qiáng)大的功能和如何通過(guò)示例代碼更好地利用它2023-12-12
tensorflow實(shí)現(xiàn)殘差網(wǎng)絡(luò)方式(mnist數(shù)據(jù)集)
這篇文章主要介紹了tensorflow實(shí)現(xiàn)殘差網(wǎng)絡(luò)方式(mnist數(shù)據(jù)集),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05
Python面向?qū)ο笾蓄悾╟lass)的簡(jiǎn)單理解與用法分析
這篇文章主要介紹了Python面向?qū)ο笾蓄悾╟lass)的簡(jiǎn)單理解與用法,結(jié)合實(shí)例形式分析了Python面向?qū)ο蟪绦蛟O(shè)計(jì)中類(class)的基本概念、原理、定義與使用方法,需要的朋友可以參考下2020-02-02
Python多線程與多進(jìn)程相關(guān)知識(shí)總結(jié)
進(jìn)程(process)和線程(thread)是操作系統(tǒng)的基本概念,是操作系統(tǒng)程序運(yùn)行的基本單元,本文簡(jiǎn)要介紹進(jìn)程和線程的概念以及Python中的多進(jìn)程和多線程.需要的朋友可以參考下2021-05-05
Pycharm2020.1安裝無(wú)法啟動(dòng)問(wèn)題即設(shè)置中文插件的方法
這篇文章主要介紹了Pycharm2020.1安裝無(wú)法啟動(dòng)問(wèn)題即設(shè)置中文插件的操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2020-08-08

