django中的select_related和prefetch_related性能優(yōu)化分析
django中的ORM查詢,針對(duì)復(fù)雜的查詢,除了使用A.objects.filter(foreign_name__field)進(jìn)行查詢外。還可以使用select_related 和prefetch_related,進(jìn)行性能的優(yōu)化
select_related:
將會(huì)根據(jù)外鍵關(guān)系(注意: 僅限單對(duì)單和單對(duì)多關(guān)系),在執(zhí)行查詢語句的時(shí)候通過創(chuàng)建一條包含SQL inner join操作的SELECT語句來一次性獲得主對(duì)象及相關(guān)對(duì)象的信息
1、模型類創(chuàng)建
users/modes.py
from django.db import models # Create your models here. class UserInfo(models.Model): username = models.CharField(verbose_name='用戶名', max_length=225) def __str__(self): return self.username class Meta: db_table = 'userinfo' class Tag(models.Model): name = models.CharField(verbose_name='標(biāo)簽名稱', max_length=225) def __str__(self): return self.name class Meta: db_table = 'tag' class Article(models.Model): title = models.CharField(verbose_name='標(biāo)題', max_length=225) content = models.CharField(verbose_name='內(nèi)容', max_length=225) # 外鍵 username = models.ForeignKey(verbose_name='用戶', to='UserInfo', on_delete=models.DO_NOTHING) tag = models.ManyToManyField(verbose_name='標(biāo)簽', to='Tag') def __str__(self): return self.title class Meta: db_table = 'article'
2、添加admin站點(diǎn),插入測(cè)試數(shù)據(jù)
user/admin.py
from django.contrib import admin from .models import Article, UserInfo, Tag # Register your models here. admin.site.register(UserInfo) admin.site.register(Article) admin.site.register(Tag)
3、select_related示例查詢
3.1 普通查詢
<h1>article列表</h1> <body> <ul> {% for article in article_queryset %} <li>{{ article.title }} <==> {{ article.title }}</li> {% endfor %} </ul> </body>
def article_list0(request): if request.method == 'GET': article_queryset = Article.objects.all() return render(request, 'user/t1.html', {'article_queryset': article_queryset})
以上可知:只有一次SQL查詢記錄
3.2 外鍵查詢
<h1>article列表</h1> <body> <ul> {% for article in article_queryset %} <li>{{ article.title }} <==> {{ article.username }}</li> {% endfor %} </ul> </body>
def article_list(request): if request.method == 'GET': article_queryset = Article.objects.all() return render(request, 'user/t2.html', {'article_queryset': article_queryset})
以上可知:有13次SQL查詢
1次查詢article表,12次查詢article的外鍵
3.3 性能優(yōu)化
<h1>article列表</h1> <body> <ul> {% for article in article_queryset %} <li>{{ article.title }} <==> {{ article.username }}</li> {% endfor %} </ul> </body>
def article_list2(request): if request.method == 'GET': article_queryset = Article.objects.all().select_related('username') # article_queryset = Article.objects.all().prefetch_related() return render(request, 'user/t2.html', {'article_queryset': article_queryset})
以上可知:使用select_related進(jìn)行優(yōu)化,只有一次SQL查詢
3.4 其他示例
# 獲取id=1的文章對(duì)象同時(shí),獲取其相關(guān)username信息 Article.objects.select_related('username').get(id=1) # 獲取id=1的文章對(duì)象同時(shí),獲取其相關(guān)作者名字信息 Article.objects.select_related('username__username').get(id=1) # 獲取id=1的文章對(duì)象同時(shí),獲取其相關(guān)tag和相關(guān)作者名字信息。下面方法等同。 # 方式一: Article.objects.select_related('tag', 'username__username').get(id=1) # 方式二: Article.objects.select_related('tag').select_related('username__username').get(id=1) # 使用select_related()可返回所有相關(guān)主鍵信息。all()非必需。 Article.objects.all().select_related() # 獲取Article信息同時(shí)獲取username信息。filter方法和selected_related方法順序不重要。 # 方式一: Article.objects.filter(tag__gt=3).select_related('username') # 方式二: Article.objects.select_related('username').filter(tag__gt=3)
4、prefetch_related示例查詢
對(duì)于多對(duì)多字段,你不能使用select_related方法,這樣做是為了避免對(duì)多對(duì)多字段執(zhí)行JOIN操作從而造成最后的表非常大。
prefetch_related()和select_related()的設(shè)計(jì)目的很相似,都是為了減少SQL查詢的數(shù)量,但是實(shí)現(xiàn)的方式不一樣。后者是通過JOIN語句,在SQL查詢內(nèi)解決問題。但是對(duì)于多對(duì)多關(guān)系,使用SQL語句解決就顯得有些不太明智,因?yàn)镴OIN得到的表將會(huì)很長(zhǎng),會(huì)導(dǎo)致SQL語句運(yùn)行時(shí)間的增加和內(nèi)存占用的增加。若有n個(gè)對(duì)象,每個(gè)對(duì)象的多對(duì)多字段對(duì)應(yīng)Mi條,就會(huì)生成Σ(n)Mi 行的結(jié)果表。
4.1 普通查詢
<h1>{{ tag.name }}</h1> <body> <ul> {% for article in article_list %} <li>{{ article.title }}</li> {% endfor %} </ul> </body>
def tag_list(request, tid): if request.method == 'GET': tag = Tag.objects.get(pk=tid) article_list = tag.article_set.all() return render(request, 'user/t4.html', {'tag': tag, 'article_list': article_list})
4.2 性能優(yōu)化
<h1>{{ tag.name }}</h1> <body> <ul> {% for article in tag.article_set.all %} <li>{{ article.title }}</li> {% endfor %} </ul> </body>
def tag_list1(request, tid): if request.method == 'GET': tag = Tag.objects.prefetch_related('article_set').get(pk=tid) return render(request, 'user/t5.html', {'tag': tag})
到此這篇關(guān)于django之select_related、prefetch_related的文章就介紹到這了,更多相關(guān)django select_related、prefetch_related內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Django中select_related和prefetch_related的用法與區(qū)別詳解
- 利用Django框架中select_related和prefetch_related函數(shù)對(duì)數(shù)據(jù)庫查詢優(yōu)化
- Python的Django框架中的select_related函數(shù)對(duì)QuerySet 查詢的優(yōu)化
- Django中prefetch_related()函數(shù)優(yōu)化實(shí)戰(zhàn)指南
- Django中QuerySet查詢優(yōu)化之prefetch_related詳解
- 用實(shí)例詳解Python中的Django框架中prefetch_related()函數(shù)對(duì)數(shù)據(jù)庫查詢的優(yōu)化
相關(guān)文章
關(guān)于python3的ThreadPoolExecutor線程池大小設(shè)置
這篇文章主要介紹了關(guān)于python3的ThreadPoolExecutor線程池大小設(shè)置,線程池的理想大小取決于被提交任務(wù)的類型以及所部署系統(tǒng)的特性,需要的朋友可以參考下2023-04-04python 實(shí)現(xiàn)socket服務(wù)端并發(fā)的四種方式
這篇文章主要介紹了python 實(shí)現(xiàn)socket服務(wù)端并發(fā)的四種方式,幫助大家更好的理解和使用python,感興趣的朋友可以了解下2020-12-12python?數(shù)據(jù)保存為npy和npz格式并讀取的完整代碼
這篇文章主要介紹了python?數(shù)據(jù)保存為npy和npz格式并讀取,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07python查找目錄下指定擴(kuò)展名的文件實(shí)例
這篇文章主要介紹了python查找目錄下指定擴(kuò)展名的文件,實(shí)例分析了Python文件查詢的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04Python字符串對(duì)象實(shí)現(xiàn)原理詳解
這篇文章主要介紹了Python字符串對(duì)象實(shí)現(xiàn)原理詳解,在Python世界中將對(duì)象分為兩種:一種是定長(zhǎng)對(duì)象,比如整數(shù),整數(shù)對(duì)象定義的時(shí)候就能確定它所占用的內(nèi)存空間大小,另一種是變長(zhǎng)對(duì)象,在對(duì)象定義時(shí)并不知道是多少,需要的朋友可以參考下2019-07-07Python中requirements.txt簡(jiǎn)介(推薦)
Python項(xiàng)目中必須包含一個(gè)?requirements.txt?文件,用于記錄所有依賴包及其精確的版本號(hào),以便新環(huán)境部署,這篇文章主要介紹了Python中requirements.txt簡(jiǎn)介,需要的朋友可以參考下2022-11-11Python利用PyPDF2庫實(shí)現(xiàn)輕松提取PDF文本
ython中的PyPDF2庫是一個(gè)非常有用的工具,無論您是需要分析PDF文檔中的內(nèi)容還是需要在文檔中搜索特定的信息,PyPDF2都可以幫助您輕松實(shí)現(xiàn)這些任務(wù),下面我們就來學(xué)習(xí)一下如何利用PyPDF2提取PDF文本吧2023-09-09