[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-首页模板