关于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数组的处理代码
Jan 04 Python
python实现目录树生成示例
Mar 28 Python
Python抓取电影天堂电影信息的代码
Apr 07 Python
使用python实现tcp自动重连
Jul 02 Python
CentOS中升级Python版本的方法详解
Jul 10 Python
Python爬取十篇新闻统计TF-IDF
Jan 03 Python
python网络爬虫学习笔记(1)
Apr 09 Python
PyTorch实现更新部分网络,其他不更新
Dec 31 Python
tensorflow 报错unitialized value的解决方法
Feb 06 Python
如何安装并在pycharm使用selenium的方法
Apr 30 Python
Python urlopen()参数代码示例解析
Dec 10 Python
使用tensorflow 实现反向传播求导
May 26 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 默默经典版本
2009/08/04 PHP
限制ckeditor上传图片文件大小的方法
2013/11/15 PHP
Thinkphp实现短信验证注册功能
2016/10/18 PHP
php微信公众号开发之音乐信息
2018/10/20 PHP
PHP+Ajax实现的检测用户名功能简单示例
2019/02/12 PHP
PHP goto语句用法实例
2019/08/06 PHP
php让json_encode不自动转义斜杠“/”的方法
2020/04/27 PHP
用js实现上传图片前的预览(TX的面试题)
2007/08/14 Javascript
找到了一篇jQuery与Prototype并存的冲突的解决方法
2007/08/29 Javascript
js触发select onchange事件的小技巧
2014/08/05 Javascript
用js通过url传参把数据从一个页面传到另一个页面
2014/09/01 Javascript
超棒的响应式布局jQuery插件Freetile.js
2014/11/17 Javascript
JavaScript实现的简单烟花特效代码
2015/10/20 Javascript
javascript实现2016新年版日历
2016/01/25 Javascript
JS验证逗号隔开可以是中文字母数字
2016/04/22 Javascript
JavaScript 函数的执行过程
2016/05/09 Javascript
基于jQuery的Web上传插件Uploadify使用示例
2016/05/19 Javascript
完美实现八种js焦点轮播图(下篇)
2020/04/20 Javascript
微信小程序 Canvas增强组件实例详解及源码分享
2017/01/04 Javascript
一个简易时钟效果js实现代码
2020/03/25 Javascript
MUI 实现侧滑菜单及其主体部分上下滑动的方法
2018/01/25 Javascript
Angular中sweetalert弹框的基本使用教程
2018/07/22 Javascript
JavaScript中变量、指针和引用功能与操作示例
2018/08/04 Javascript
vue中多路由表头吸顶实现的几种布局方式
2019/04/12 Javascript
一篇文章带你使用Typescript封装一个Vue组件(简单易懂)
2020/06/05 Javascript
[01:10]3.19DOTA2发布会 三代刀塔人第一代
2014/03/25 DOTA
Python实现同时兼容老版和新版Socket协议的一个简单WebSocket服务器
2014/06/04 Python
python3 shelve模块的详解
2017/07/08 Python
Python中实现最小二乘法思路及实现代码
2018/01/04 Python
python 将字符串完成特定的向右移动方法
2019/06/11 Python
python实现局域网内实时通信代码
2019/12/22 Python
如何用PyPy让你的Python代码运行得更快
2020/12/02 Python
Pandas DataFrame求差集的示例代码
2020/12/13 Python
村委会换届选举方案
2014/05/03 职场文书
spring boot中nativeQuery的用法
2021/07/26 Java/Android
面试中canvas绘制图片模糊图片问题处理
2022/03/13 Javascript