关于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之字典,你还记得吗?
Sep 20 Python
Python实现从脚本里运行scrapy的方法
Apr 07 Python
Python中pygame安装方法图文详解
Nov 11 Python
Python有序字典简单实现方法示例
Sep 28 Python
Python读取properties配置文件操作示例
Mar 29 Python
python批量修改文件夹及其子文件夹下的文件内容
Mar 15 Python
通过python实现windows桌面截图代码实例
Jan 17 Python
Python中flatten( ),matrix.A用法说明
Jul 05 Python
简单了解Django项目应用创建过程
Jul 06 Python
windows安装python超详细图文教程
May 21 Python
Python趣味挑战之用pygame实现简单的金币旋转效果
May 31 Python
Python中的pprint模块
Nov 27 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购物网站支付paypal使用方法
2010/11/28 PHP
学习php过程中的一些注意点的总结
2013/10/25 PHP
PHP+Ajax实现无刷新分页实例详解(附demo源码下载)
2016/04/07 PHP
php从身份证获取性别和出生年月
2017/02/09 PHP
PHP实现的MD5结合RSA签名算法实例
2017/10/07 PHP
定位地理位置PHP判断员工打卡签到经纬度是否在打卡之内
2019/05/23 PHP
InnerHtml和InnerText的区别分析
2009/03/13 Javascript
JS中判断null、undefined与NaN的方法
2014/03/24 Javascript
jQuery操作Table技巧大汇总
2016/01/23 Javascript
angularjs 源码解析之injector
2016/08/22 Javascript
JS版微信6.0分享接口用法分析
2016/10/13 Javascript
Bootstrap分页插件之Bootstrap Paginator实例详解
2016/10/15 Javascript
微信 java 实现js-sdk 图片上传下载完整流程
2016/10/21 Javascript
正则表达式基本语法及表单验证操作详解【基于JS】
2017/04/07 Javascript
Cookies 和 Session的详解及区别
2017/04/21 Javascript
基于DOM节点删除之empty和remove的区别(详解)
2017/09/11 Javascript
js计算两个日期间的天数月的实例代码
2018/09/20 Javascript
JS使用Prim算法和Kruskal算法实现最小生成树
2019/01/17 Javascript
JS多个异步请求 按顺序执行next实现解析
2019/09/16 Javascript
Layui动态生成select下拉选择框不显示的解决方法
2019/09/24 Javascript
[52:09]2014 DOTA2华西杯精英邀请赛 5 25 NewBee VS DK第二场
2014/05/26 DOTA
[04:13]2018国际邀请赛典藏宝瓶Ⅱ饰品一览
2018/07/21 DOTA
Python中的多重装饰器
2015/04/11 Python
python append、extend与insert的区别
2016/10/13 Python
Ubuntu 16.04 LTS中源码安装Python 3.6.0的方法教程
2016/12/27 Python
神经网络理论基础及Python实现详解
2017/12/15 Python
Apache,wsgi,django 程序部署配置方法详解
2019/07/01 Python
python实现简单贪吃蛇游戏
2020/09/29 Python
Camille Jewelry官网:现代女性时尚首饰
2019/07/07 全球购物
教师业务学习制度
2014/01/25 职场文书
老总助理工作岗位职责
2014/02/06 职场文书
农民工讨薪标语
2014/06/26 职场文书
安全资料员岗位职责范本
2014/06/28 职场文书
党校毕业个人总结
2015/02/28 职场文书
公司老总年会致辞
2015/07/30 职场文书
Python使用random模块实现掷骰子游戏的示例代码
2021/04/29 Python