关于Django ForeignKey 反向查询中filter和_set的效率对比详解


Posted in Python onDecember 15, 2018

前言

大家使用 Django 创建模型的时候一定会经常使用 ForeignKey 来创建两个表格之间多对一的外键关系,例如B中有一个 models.ForeignKey(A) 。而当我们需要反向查询 A 中某个具体实例所关联的 B 时,可能会用到 A.B_set.all() 或 B.objects.filter(A) 这两种不同的方法。

不知道大家有没有也想过一个问题:当网站实际上线后,SEO强调页面加载速度,而当面对不断增大的请求量,这两种方法的哪一种速度更快?

馆主我产生了这个疑问,所以就打算跑一下试试看看。馆主尚属小白,如有不对的地方,还请各位客官登录一下账号,留言指点!

实验环境

操作系统: Manjaro Linux 17.1-rc2 
Python: Python 3.6.3 
Django: Django 1.11.7 
数据库: SQLite 3.21.0 
CPU: i3-4130 @ 3.4GHz 
内存: DDR3 1600 8G + 4G

实验计划

分别创建“问题”模型 Questions 和“答案”模型 Answers ,答案模型对于问题模型存在多对一关系 ForeignKey 创建一个问题和两个答案。然后分别使用两种不同的方法运行查询数据 10000 次比较消耗的时间。

实验实施

创建实验模型

# myapp/models.py

from django.db import models

class Questions(models.Model):
  '''问题的模型'''
  title = models.CharField('标题', max_length=100)
  content = models.TextField('描述')


class Answers(models.Model):
  '''答案的模型'''
  question = models.ForeignKey(Questions, on_delete=models.CASCADE, verbose_name='问题')
  content = models.TextField('答案')

然后我们进入 django 的 shell 为模型增加数据并编写我们的测试。

>>> from myapp.models import Questions, Answers

# 创建第一个问题
Questions.objects.create(
  title = '这是第一个问题么?'
  content = '我认为这是第一个问题,不知道是不是真的啊?'
  )

# 创建第一个答案
Answers.objects.create(
  question = Questions.objects.get(pk=1),
  content = '你说对了了,这是第一个问题'
  )


# 创建第二个答案
Answers.objects.create(
  question = Questions.objects.get(pk=1),
  content = '题主,你是第一个问题,但我是第二个答案么?'
  )

利用 timeit 测试两种方法消耗的时间

from timeit import timeit

# 构建使用 _set 方法的函数
def time_test_1():
  question = Question.objects.get(pk=1)
  answers = question.answers_set.all()


# 构建使用 filter 方法的函数
def time_test_2():
  question = Question.objects.get(pk=1)
  answers = Answers.objects.filter(question=question)

# 使用 timeit 测试 10000 次
timeit(time_test_1, number=10000)
5.346277045000534

timeit(time_test_2, number=10000)
5.11136907800028

实际经过多次测试,至少我这样的用法来看 使用A.B_set.all() 反向查询消耗的时间总是比 B.objects.filter(A) 过滤筛选方法多消耗 0.2 - 0.3 秒钟左右。所以但从时间成本来考虑的话还是使用 filter 筛选效率更高一些。

以上这篇关于Django ForeignKey 反向查询中filter和_set的效率对比详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
朴素贝叶斯算法的python实现方法
Nov 18 Python
python 循环while和for in简单实例
Aug 16 Python
Python实现感知机(PLA)算法
Dec 20 Python
Python实现查找最小的k个数示例【两种解法】
Jan 08 Python
python实现根据文件格式分类
Oct 31 Python
python制作朋友圈九宫格图片
Nov 03 Python
Python类反射机制使用实例解析
Dec 30 Python
python用pip install时安装失败的一系列问题及解决方法
Feb 24 Python
django使用F方法更新一个对象多个对象字段的实现
Mar 28 Python
python opencv 实现读取、显示、写入图像的方法
Jun 08 Python
解决TensorFlow调用Keras库函数存在的问题
Jul 06 Python
Python OpenCV快速入门教程
Apr 17 Python
django 外键model的互相读取方法
Dec 15 #Python
Django之Mode的外键自关联和引用未定义的Model方法
Dec 15 #Python
python调用java的jar包方法
Dec 15 #Python
对python同一个文件夹里面不同.py文件的交叉引用方法详解
Dec 15 #Python
Python数据分析:手把手教你用Pandas生成可视化图表的教程
Dec 15 #Python
浅谈python 导入模块和解决文件句柄找不到问题
Dec 15 #Python
对python当中不在本路径的py文件的引用详解
Dec 15 #Python
You might like
php上传文件中文文件名乱码的解决方法
2013/11/01 PHP
php中http与https跨域共享session的解决方法
2014/12/20 PHP
PHP数据库操作三:redis用法分析
2017/08/16 PHP
解决thinkPHP 5 nginx 部署时,只跳转首页的问题
2019/10/16 PHP
详解阿里云视频直播PHP-SDK接入教程
2020/07/09 PHP
Javascript学习笔记5 类和对象
2010/01/11 Javascript
由JavaScript中call()方法引发的对面向对象继承机制call的思考
2011/09/12 Javascript
深入理解JavaScript系列(7) S.O.L.I.D五大原则之开闭原则OCP
2012/01/15 Javascript
用IE重起计算机或者关机的示例代码
2014/03/10 Javascript
jquery中push()的用法(数组添加元素)
2014/11/25 Javascript
NodeJS中利用Promise来封装异步函数
2015/02/25 NodeJs
javascript常用功能汇总
2015/07/05 Javascript
基于React实现表单数据的添加和删除详解
2017/03/14 Javascript
javascript实现table单元格点击展开隐藏效果(实例代码)
2017/04/10 Javascript
深入浅析Vue不同场景下组件间的数据交流
2017/08/15 Javascript
AngularJS实现的base64编码与解码功能示例
2018/05/17 Javascript
vue中组件通信的八种方式(值得收藏!)
2019/08/09 Javascript
React倒计时功能实现代码——解耦通用
2020/09/18 Javascript
解决vue init webpack 下载依赖卡住不动的问题
2020/11/09 Javascript
[06:01]刀塔次级联赛top10第一期
2014/11/07 DOTA
python sqlobject(mysql)中文乱码解决方法
2008/11/14 Python
pymssql ntext字段调用问题解决方法
2008/12/17 Python
通过python+selenium3实现浏览器刷简书文章阅读量
2017/12/26 Python
Python 25行代码实现的RSA算法详解
2018/04/10 Python
Python使用re模块实现信息筛选的方法
2018/04/29 Python
Python实现登陆文件验证方法
2018/10/06 Python
通过shell+python实现企业微信预警
2019/03/07 Python
Python参数解析模块sys、getopt、argparse使用与对比分析
2019/04/02 Python
PyCharm 2020.2 安装详细教程
2020/09/25 Python
SOA的常见陷阱或者误解是什么
2014/10/05 面试题
经销商订货会主持词
2014/03/27 职场文书
老龄工作先进事迹
2014/08/15 职场文书
合同纠纷调解书
2015/05/20 职场文书
2016年寒假社会实践活动心得体会
2015/10/09 职场文书
Golang的继承模拟实例
2021/06/30 Golang
动作冒险《Hell Is Us》将采用虚幻5 消灭怪物探索王国
2022/04/13 其他游戏