[TOC]
>[success] # 常見錯誤N+1 問題
~~~
就是往往不注意循環中的orm 處理,導致出現N+1的問題,進而導致系統變慢,
然后拖垮整個系統。
~~~
>[success] # 常見的幾種N+1
>[danger] ##### 沒有合理使用derfer
~~~
1.derfer 是查詢除了什么字段以外的字段
2.下面是在單元測試寫的一個小案例,我們主要關心這段代碼
categories = Categroy.objects.defer('name')
for i in categories:
print(i.name)
~~~
~~~
@override_settings(DEBUG=True)
def set_filter(self):
categories = Categroy.objects.exists()
print(categories)
categories = Categroy.objects.defer('name')
for i in categories:
print(i.name)
print(categories)
# categories = categories.filter(status=1)
pp(connection.queries)
~~~
* 實際產生的sql
~~~
1.第一次查詢,實在for i in categories 打印出來的,不是在創建的時候因為懶加載機制
---'SELECT "blong_categroy"."id", "blong_categroy"."status", '
'"blong_categroy"."is_nav", "blong_categroy"."owner_id", '
'"blong_categroy"."created_time" FROM "blong_categroy"',
'time'
2.當我們i.name 由于derfer 是除了name 字段以外的字段查詢,我們
卻偏偏打印了這個字段就產生了下面N的情況
--'SELECT "blong_categroy"."id", "blong_categroy"."name" FROM '
'"blong_categroy" WHERE "blong_categroy"."id" = 1
乘循環次數的N,其中為什么是N次,因為我們給查詢每個id 的name,所以相當于執行了N次的where條件id=1 id=2 .....直到最后一個id
~~~
>[danger] ##### only
~~~
1.only 是只查詢這個字段
2.下面是在單元測試寫的一個小案例,我們主要關心這段代碼
def set_filter(self):
categories = Categroy.objects.only('name')
for i in categories:
print(i.created_time)
~~~
~~~
@override_settings(DEBUG=True)
def set_filter(self):
categories = Categroy.objects.only('name')
for i in categories:
print(i.created_time)
print(categories)
# categories = categories.filter(status=1)
pp(connection.queries)
~~~
* 實際產生的sql
~~~
1.第一次查詢,實在for i in categories 打印出來的,不是在創建的時候因為懶加載機制
---' 'SELECT "blong_categroy"."id", "blong_categroy"."name" FROM '
'"blong_categroy"'
2.當我們查詢i.created_time 由于only是只查詢什么字段, 導致由于id是唯一的所以,判斷條件要where 每一個id查詢結果
卻偏偏打印了這個字段就產生了下面N的情況
--'SSELECT "blong_categroy"."id", "blong_categroy"."created_time" FROM '
'"blong_categroy" WHERE "blong_categroy"."id" = 1',
乘循環次數的N,其中為什么是N次,因為我們給查詢每個id created_time,所以相當于執行了N次的where條件id=1 id=2 .....直到最后一個id
~~~
>[danger] ##### 關聯對象
~~~
1.當我們兩個表做了關聯的時候也就是ForeignKey的時候,我們可能最容易忽略
這個n+1的問題,兩個表的關聯查詢 在sql語句上我們通常使用jion on 如果不使
用,我們看看執行情況,這是表的創建展示
class Categroy(models.Model):
STATUS_ITMES = (
(1, "正常"),
(2, "刪除"),
)
name = models.CharField(max_length=50, verbose_name="名稱")
status = models.PositiveIntegerField(default=1, choices=STATUS_ITMES, verbose_name="狀態")
is_nav = models.BooleanField(default=False, verbose_name="是否為導航")
owner = models.ForeignKey(User, verbose_name="作者")
created_time = models.DateTimeField(auto_now_add=True, verbose_name="創建時間")
class Meta:
verbose_name = verbose_name_plural = '分類'
~~~
* 問題我們想去查關聯表,我們來看看 常見的N+1 錯誤
~~~
@override_settings(DEBUG=True)
def set_filter(self):
categories = Categroy.objects.all()
for i in categories:
print(i.owner)
# categories = categories.filter(status=1)
pp(connection.queries)
~~~
~~~
1.上面的代碼有一個很嚴重的N+1問題
2.其實每一打印的owner 對象實際是又重新生成了sql 語句,如下展示
--- SELECT "blong_categroy"."id", "blong_categroy"."name", '
'"blong_categroy"."status", "blong_categroy"."is_nav", '
'"blong_categroy"."owner_id", "blong_categroy"."created_time" FROM '
'"blong_categroy"',
'time'
3.打印查詢了N邊的,其中N 是where 條件中的id
----'SELECT "auth_user"."id", "auth_user"."password", '
'"auth_user"."last_login", "auth_user"."is_superuser", '
'"auth_user"."username", "auth_user"."first_name", '
'"auth_user"."last_name", "auth_user"."email", '
'"auth_user"."is_staff", "auth_user"."is_active", '
'"auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = '
'1',
~~~
* 怎么解決這樣問題--select_related() 來解決這個問題
~~~
@override_settings(DEBUG=True)
def set_filter(self):
categories = Categroy.objects.select_related().filter(status=1)
for i in categories:
print(i.owner)
# categories = categories.filter(status=1)
pp(connection.queries)
~~~
* 執行的sql 語句用jion on 吧ower 對象查詢,這樣我們就可以直接操對象而不是他的本身
~~~
'SELECT "blong_categroy"."id", "blong_categroy"."name", '
'"blong_categroy"."status", "blong_categroy"."is_nav", '
'"blong_categroy"."owner_id", "blong_categroy"."created_time", '
'"auth_user"."id", "auth_user"."password", "auth_user"."last_login", '
'"auth_user"."is_superuser", "auth_user"."username", '
'"auth_user"."first_name", "auth_user"."last_name", '
'"auth_user"."email", "auth_user"."is_staff", '
'"auth_user"."is_active", "auth_user"."date_joined" FROM '
'"blong_categroy" INNER JOIN "auth_user" ON '
'("blong_categroy"."owner_id" = "auth_user"."id") WHERE '
'"blong_categroy"."status" = 1',
~~~
- 網絡原理
- 為搭建框架做準備
- 簡單認識網路
- 自定義模擬網站案例
- 優化最終框架
- 數據存儲 -- data
- 用戶個人信息存儲 -- User.txt
- 路由映射 -- routes
- 處理用戶信息 -- routes_static.py
- 保存靜態文件 -- static
- templates -- html 集中處理模塊
- 首頁 -- index.html
- 登陸 -- login.html
- 用戶注冊頁面 -- register
- 日志模塊 -- log.gua.txt
- 啟動文件--server.py
- orm處理 -- model.py
- 日志模塊 -- utils.py
- 兩種數據庫類型
- 傳統數據庫了解篇
- 前端快速入門
- JS簡單使用入門
- css簡單快速入門
- DJANGO
- virtualenv-創建虛擬環境
- 項目結構
- django-admin中文配置
- django-打印sql語句
- django-基礎
- 認識MVC和MTV
- Django--初識
- Django--初識案例
- Django-FBV/CBV
- Django--常用input 交互
- Django-url
- Django-url.py 配置
- Django-include 使用
- Django-url name
- Django-ORM
- ORM-數據庫配置
- ORM-model字段
- ORM-model字段解釋
- ORM-字段選項
- ORM-查詢
- ORM-四種常用查詢方法
- ORM-三種獲取數據
- ORM-其他查詢方式
- ORM-條件查詢雙線
- ORM-Q和F條件使用
- ORM-三種數據庫交互
- 案例 -- 一對多
- ORM-技巧/常見問題
- ORM-N+1 問題
- ORM-并發的處理
- ORM-數量查詢、
- ORM-正向反向查詢
- ORM-基礎案例一
- ORM-基礎一對多案例
- Django-templates
- Django-模板的繼承
- Django-模板的過濾
- Django-自定義模板的過濾
- Django-cookie
- Django-cookies 裝飾器
- Djang-session
- Django-CSRF
- Django-中間件 -- 后續了解
- Django- 緩存 -- 沒有深入了解
- Django-form
- From-ajax
- form-內部驗證處理
- form-屬性
- form-常用的標簽字段
- form-常用的下拉和選擇
- form-widget速查
- Django-ajax序列化
- Django-多種ajax寫法
- ajax-原生寫法
- ajax-$寫法
- ajax-ifram
- Django-ajax圖片上傳
- ajax-原始寫法
- ajax-正常寫法
- iframe+form
- 實戰寫法
- Django-常用自編寫組件
- Django-雙菜單組合搜索
- Django - 多菜單組合搜索
- Django-分頁
- django-綜合基礎
- 綜合基礎-render
- django-admin
- admin-頁面配置
- admin-字段配置
- admin-編輯頁面
- admin-forms驗證
- admin-創建抽象類
- django-驗證碼
- 驗證碼-第三方生成庫
- 驗證碼-view.py使用
- 驗證碼-注意引入Monaco.ttf
- django-用戶注冊
- 注冊-form 模塊
- 注冊-views 模塊
- 注冊-html模塊
- 注冊-model模塊
- django-用戶登錄三種
- session登錄
- form-session 寫法
- view-寫法
- Html-寫法
- model-寫法
- 繼承類登錄
- 外鍵關聯登錄
- django-簡單的student 管理案例
- app-urls.py
- app-models.py配置
- admin-admin.py配置
- app-form.py 和數據庫關聯的寫法
- app-FBV_views.py
- app-CBV_views.py
- templates-index.html
- django-博客系統
- APP目錄-models.py 創建
- APP目錄-基礎展示數據分析
- APP目錄-基礎數據展示cls
- ListView
- DetailView
- FormView
- 額外功能拓建
- 添加文章搜索/用戶文章查詢功能
- 增加一個友情鏈接
- 增加一個評論模塊
- App-利用Bootstrap4 搭建樣式
- 項目crm
- 思維導圖
- perfectCRM-項目名字
- settings.py-配置
- view.py-登陸/登出函數
- crm-app文件
- model.py-表的創建
- admin.py-注冊后臺
- view.py-視圖層
- static-靜態文件
- css
- bootstrap.min.css
- dashboard.css
- ie10-viewport-bug-workaround.css
- signin.css
- fonts
- imgs
- js
- jquery.js
- bootstrap.min.js
- holeder.js
- ie10-viewport-bug-workaround.js
- ie-emulation-modes-warning.js
- plugins
- html模板文件-templates
- crm
- index.html-首頁模板