django中的select_related和prefetch_related性能優(yōu)化分析
django中的ORM查詢,針對復雜的查詢,除了使用A.objects.filter(foreign_name__field)進行查詢外。還可以使用select_related 和prefetch_related,進行性能的優(yōu)化
select_related:
將會根據(jù)外鍵關(guān)系(注意: 僅限單對單和單對多關(guān)系),在執(zhí)行查詢語句的時候通過創(chuàng)建一條包含SQL inner join操作的SELECT語句來一次性獲得主對象及相關(guān)對象的信息
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='標簽名稱', max_length=225) def __str__(self): return self.name class Meta: db_table = 'tag' class Article(models.Model): title = models.CharField(verbose_name='標題', 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='標簽', to='Tag') def __str__(self): return self.title class Meta: db_table = 'article'
2、添加admin站點,插入測試數(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進行優(yōu)化,只有一次SQL查詢
3.4 其他示例
# 獲取id=1的文章對象同時,獲取其相關(guān)username信息 Article.objects.select_related('username').get(id=1) # 獲取id=1的文章對象同時,獲取其相關(guān)作者名字信息 Article.objects.select_related('username__username').get(id=1) # 獲取id=1的文章對象同時,獲取其相關(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信息同時獲取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示例查詢
對于多對多字段,你不能使用select_related方法,這樣做是為了避免對多對多字段執(zhí)行JOIN操作從而造成最后的表非常大。
prefetch_related()和select_related()的設(shè)計目的很相似,都是為了減少SQL查詢的數(shù)量,但是實現(xiàn)的方式不一樣。后者是通過JOIN語句,在SQL查詢內(nèi)解決問題。但是對于多對多關(guān)系,使用SQL語句解決就顯得有些不太明智,因為JOIN得到的表將會很長,會導致SQL語句運行時間的增加和內(nèi)存占用的增加。若有n個對象,每個對象的多對多字段對應Mi條,就會生成Σ(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Django中select_related和prefetch_related的用法與區(qū)別詳解
- 利用Django框架中select_related和prefetch_related函數(shù)對數(shù)據(jù)庫查詢優(yōu)化
- Python的Django框架中的select_related函數(shù)對QuerySet 查詢的優(yōu)化
- Django中prefetch_related()函數(shù)優(yōu)化實戰(zhàn)指南
- Django中QuerySet查詢優(yōu)化之prefetch_related詳解
- 用實例詳解Python中的Django框架中prefetch_related()函數(shù)對數(shù)據(jù)庫查詢的優(yōu)化
相關(guān)文章
關(guān)于python3的ThreadPoolExecutor線程池大小設(shè)置
這篇文章主要介紹了關(guān)于python3的ThreadPoolExecutor線程池大小設(shè)置,線程池的理想大小取決于被提交任務的類型以及所部署系統(tǒng)的特性,需要的朋友可以參考下2023-04-04python 實現(xiàn)socket服務端并發(fā)的四種方式
這篇文章主要介紹了python 實現(xiàn)socket服務端并發(fā)的四種方式,幫助大家更好的理解和使用python,感興趣的朋友可以了解下2020-12-12python?數(shù)據(jù)保存為npy和npz格式并讀取的完整代碼
這篇文章主要介紹了python?數(shù)據(jù)保存為npy和npz格式并讀取,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07Python利用PyPDF2庫實現(xiàn)輕松提取PDF文本
ython中的PyPDF2庫是一個非常有用的工具,無論您是需要分析PDF文檔中的內(nèi)容還是需要在文檔中搜索特定的信息,PyPDF2都可以幫助您輕松實現(xiàn)這些任務,下面我們就來學習一下如何利用PyPDF2提取PDF文本吧2023-09-09