Django中select_related和prefetch_related的用法與區(qū)別詳解
0. 本文借助django-debug-toolbar來展現(xiàn)效果
django-debug-toolbar的安裝
1. 介紹
select_related:
將會根據(jù)外鍵關(guān)系(注意: 僅限單對單和單對多關(guān)系),在執(zhí)行查詢語句的時候通過創(chuàng)建一條包含SQL inner join操作的SELECT語句來一次性獲得主對象及相關(guān)對象的信息
prefetch_related
對于多對多字段,你不能使用select_related方法,這樣做是為了避免對多對多字段執(zhí)行JOIN操作從而造成最后的表非常大。
Django提供了prefect_related方法來解決這個問題。
prefect_related可用于多對多關(guān)系字段,也可用于反向外鍵關(guān)系(related_name)。
相同點:
都作用于queryset對象上面
注意點:
- 對與單對單或單對多外鍵ForeignKey字段,使用select_related方法
- 對于多對多字段和反向外鍵關(guān)系,使用prefetch_related方法
- 兩種方法均支持雙下劃線指定需要查詢的關(guān)聯(lián)對象的字段名
- 使用Prefetch方法可以給prefetch_related方法額外添加額外條件和屬性。
2. 使用
表
from django.db import models class UserInfo(models.Model): username = models.CharField(verbose_name='用戶名', max_length=225) def __str__(self): return self.username class Tag(models.Model): name = models.CharField(verbose_name='標簽名稱', max_length=225) def __str__(self): return self.name 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
2.1 原生的查詢
2.1.1 代碼
def article_list(request): if request.method == 'GET': # select_related---->queryset article_queryset = models.Article.objects.all() return render(request, 't2.html', context={'article_queryset': article_queryset})
2.1.2 圖示
2.1.3 查詢解釋
1.從圖示我們可以看出來,一共進行13次查詢,且有10次重復(fù)的?。。?/p>
原因是:當我們第一次查詢時,返回的值,只有文章對象,對于標簽以及用戶,并沒有查詢,當前端界面需要這兩個時,每循環(huán)一次,就會去數(shù)據(jù)庫查詢一次
2.為了避免重復(fù)查詢,django提供select_related和prefetch_related方法來提升數(shù)據(jù)庫查詢效率,類似于SQL的JOIN方法。
3.效果就是當?shù)谝淮尾樵儠r,進行連表,一次性把所有數(shù)據(jù)全部查詢到
2.2 使用select_related
2.2.2 代碼
from django.shortcuts import render from blog import models def article_list(request): if request.method == 'GET': # select_related---->queryset article_queryset = models.Article.objects.all().select_related('tag', 'username') return render(request, 't2.html', context={'article_queryset': article_queryset})
2.2.3 圖示
2.2.4 解釋
可以看到現(xiàn)在只有三次查詢,耗時大大減少
2.2.5 其他常用用法
# 獲取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)
2.3. 使用prefetch_related方法
對于多對多字段,你不能使用select_related方法,這樣做是為了避免對多對多字段執(zhí)行JOIN操作從而造成最后的表非常大。
2.3.1 常用的案例
articles = Article.objects.all().select_related('category').prefecth_related('tags') # 文章列表及每篇文章的tags對象名字信息 Article.objects.all().prefetch_related('tags__name') # 獲取id=13的文章對象同時,獲取其相關(guān)tags信息 Article.objects.prefetch_related('tags').get(id=13) # 獲取文章列表及每篇文章相關(guān)的名字以P開頭的tags對象信息 Article.objects.all().prefetch_related( Prefetch('tags', queryset=Tag.objects.filter(name__startswith="P")) ) # 文章列表及每篇文章的名字以P開頭的tags對象信息, 放在article_p_tag列表 Article.objects.all().prefetch_related( Prefetch('tags', queryset=Tag.objects.filter(name__startswith="P")), to_attr='article_p_tag' )
本文參考
Django基礎(chǔ)(29): select_related和prefetch_related的用法與區(qū)別
http://www.dbjr.com.cn/article/266493.htm
http://www.dbjr.com.cn/article/266498.htm
總結(jié)
到此這篇關(guān)于Django中select_related和prefetch_related用法與區(qū)別的文章就介紹到這了,更多相關(guān)select_related和prefetch_related用法與區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 利用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)化
- django中的select_related和prefetch_related性能優(yōu)化分析
相關(guān)文章
Python統(tǒng)計一個字符串中每個字符出現(xiàn)了多少次的方法【字符串轉(zhuǎn)換為列表再統(tǒng)計】
這篇文章主要介紹了Python統(tǒng)計一個字符串中每個字符出現(xiàn)了多少次的方法,涉及Python字符串轉(zhuǎn)換及列表遍歷、統(tǒng)計等相關(guān)操作技巧,需要的朋友可以參考下2019-05-05python 使用elasticsearch 實現(xiàn)翻頁的三種方式
這篇文章主要介紹了python 使用elasticsearch 實現(xiàn)翻頁的三種方式,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07Python3 實現(xiàn)隨機生成一組不重復(fù)數(shù)并按行寫入文件
下面小編就為大家分享一篇Python3 實現(xiàn)隨機生成一組不重復(fù)數(shù)并按行寫入文件的示例。具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04