Django批量查詢優(yōu)化的多種實現(xiàn)方案
一、基礎(chǔ)批量查詢方法
1. 批量獲取對象列表
# 獲取所有電影對象(避免內(nèi)存溢出)
films = Film.objects.all()
# 使用迭代器處理大規(guī)模數(shù)據(jù)
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. 批量值查詢(減少內(nèi)存占用)
# 只獲取需要的字段
film_titles = Film.objects.values_list('title', flat=True)
# 獲取特定字段組合
film_data = Film.objects.values('id', 'title', 'year')
二、高級批量查詢技術(shù)
1. 批量關(guān)聯(lián)查詢優(yōu)化
# 使用select_related優(yōu)化外鍵查詢
films = Film.objects.select_related('studio').all()
# 使用prefetch_related優(yōu)化多對多關(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. 批量分頁查詢
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. 批量創(chuàng)建
# 創(chuàng)建多個電影對象
films_to_create = [
Film(title="電影A", year=2023),
Film(title="電影B", year=2022),
Film(title="電影C", year=2021)
]
# 批量創(chuàng)建(返回創(chuàng)建的對象列表)
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 # 更新評分
# 批量更新到數(shù)據(jù)庫
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)對象
# 批量添加演員 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進行復(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
""")
五、實戰(zhàn)場景示例
1. 批量更新電影評分
def update_film_ratings():
# 獲取需要更新的電影
films = Film.objects.filter(year__gte=2020)
# 批量更新評分
for film in films:
film.rating = calculate_new_rating(film)
# 批量提交到數(shù)據(jù)庫
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. 批量處理電影標簽
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條記錄耗時 | 內(nèi)存占用 | 適用場景 |
|---|---|---|---|
| 普通循環(huán) | 15.2s | 高 | 小數(shù)據(jù)集 |
| bulk_create | 1.8s | 中 | 批量創(chuàng)建 |
| bulk_update | 2.1s | 中 | 批量更新 |
| 原生SQL | 0.3s | 低 | 超大規(guī)模數(shù)據(jù) |
| 分頁處理 | 8.5s | 低 | 內(nèi)存敏感場景 |
七、最佳實踐建議
選擇合適的批量大小:
- 推薦
batch_size=500-1000 - 根據(jù)數(shù)據(jù)庫性能調(diào)整
事務(wù)管理:
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)}")
# 回退或重試邏輯
性能監(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 - 高級技巧:原生SQL、事務(wù)管理
通過合理使用這些技術(shù),可以將處理10萬條記錄的時間從分鐘級降低到秒級,同時顯著減少內(nèi)存占用。關(guān)鍵是根據(jù)具體場景選擇最合適的批量處理方法,并注意錯誤處理和性能監(jiān)控。
以上就是Django批量查詢優(yōu)化的多種實現(xiàn)方案的詳細內(nèi)容,更多關(guān)于Django批量查詢優(yōu)化的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用selenium模擬登錄解決滑塊驗證問題的實現(xiàn)
這篇文章主要介紹了使用selenium模擬登錄解決滑塊驗證問題的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
python創(chuàng)建只讀屬性對象的方法(ReadOnlyObject)
有時需要創(chuàng)建一個帶只讀屬性的對象,大家可以參考下如下的方法進行創(chuàng)建,稍加改造,可以得到很特殊的效果2013-02-02
Python利用heapq實現(xiàn)一個優(yōu)先級隊列的方法
今天小編就為大家分享一篇Python利用heapq實現(xiàn)一個優(yōu)先級隊列的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-02-02

