转载自https://www.oschina.net/translate/django-querysets

对象关系映射 (ORM) 使得与SQL数据库交互更为简单,不过也被认为效率不高,比原始的SQL要慢。

要有效的使用ORM,意味着需要多少要明白它是如何查询数据库的。本文我将重点介绍如何有效使用 Django ORM系统访问中到大型的数据集。

zicode

翻译于 2013/06/18 23:29
 顶

3

 
 

Django的queryset是惰性的

Django的queryset对应于数据库的若干记录(row),通过可选的查询来过滤。例如,下面的代码会得到数据库中名字为‘Dave’的所有的人:

person_set = Person.objects.filter(first_name="Dave")

上面的代码并没有运行任何的数据库查询。你可以使用person_set,给它加上一些过滤条件,或者将它传给某个函数,这些操作都不会发送给数据库。这是对的,因为数据库查询是显著影响web应用性能的因素之一。

要真正从数据库获得数据,你需要遍历queryset:

for person in person_set:
print(person.last_name)
zicode

翻译于 2013/06/19 09:48
 顶

1

 
 

Django的queryset是具有cache的

当你遍历queryset时,所有匹配的记录会从数据库获取,然后转换成Django的model。这被称为执行(evaluation)。这些model会保存在queryset内置的cache中,这样如果你再次遍历这个queryset,你不需要重复运行通用的查询。

例如,下面的代码只会执行一次数据库查询:

pet_set = Pet.objects.filter(species="Dog")
# The query is executed and cached.
for pet in pet_set:
print(pet.first_name)
# The cache is used for subsequent iteration.
for pet in pet_set:
print(pet.last_name)
zicode

翻译于 2013/06/19 10:01
 顶

1

 
 

if语句会触发queryset的执行

queryset的cache最有用的地方是可以有效的测试queryset是否包含数据,只有有数据时才会去遍历:

restaurant_set = Restaurant.objects.filter(cuisine="Indian")
# `if`语句会触发queryset的执行。
if restaurant_set:
# 遍历时用的是cache中的数据
for restaurant in restaurant_set:
print(restaurant.name)

如果不需要所有数据,queryset的cache可能会是个问题

有时候,你也许只想知道是否有数据存在,而不需要遍历所有的数据。这种情况,简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些数据!

city_set = City.objects.filter(name="Cambridge")
# `if`语句会执行queryset.。
if city_set:
# 我们并不需要所有的数据,但是ORM仍然会获取所有记录!
print("At least one city called Cambridge still stands!")

为了避免这个,可以用exists()方法来检查是否有数据:

tree_set = Tree.objects.filter(type="deciduous")
# `exists()`的检查可以避免数据放入queryset的cache。
if tree_set.exists():
# 没有数据从数据库获取,从而节省了带宽和内存
print("There are still hardwood trees in the world!")
zicode

翻译于 2013/06/19 10:10
 顶

1

 
 

当queryset非常巨大时,cache会成为问题

处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统进程,让你的程序濒临崩溃。

要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法来获取数据,处理完数据就将其丢弃。

star_set = Star.objects.all()
# `iterator()`可以一次只从数据库获取少量数据,这样可以节省内存
for star in star_set.iterator():
print(star.name)

当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使用iterator()的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询。

zicode

翻译于 2013/06/19 14:42
 顶

1

 
 

如果查询集很大的话,if 语句是个问题

如前所述,查询集缓存对于组合 if 语句和 for 语句是很强大的,它允许在一个查询集上进行有条件的循环。然而对于很大的查询集,则不适合使用查询集缓存。

最简单的解决方案是结合使用exists()和iterator(), 通过使用两次数据库查询来避免使用查询集缓存。

molecule_set = Molecule.objects.all()
# One database query to test if any rows exist.
if molecule_set.exists():
# Another database query to start fetching the rows in batches.
for molecule in molecule_set.iterator():
print(molecule.velocity)

一个更复杂点的方案是使用 Python 的“ 高级迭代方法 ”在开始循环前先查看一下 iterator() 的第一个元素再决定是否进行循环。

atom_set = Atom.objects.all()
# One database query to start fetching the rows in batches.
atom_iterator = atom_set.iterator()
# Peek at the first item in the iterator.
try:
first_atom = next(atom_iterator)
except StopIteration:
# No rows were found, so do nothing.
pass
else:
# At least one row was found, so iterate over
# all the rows, including the first one.
from itertools import chain
for atom in chain([first_atom], atom_set):
print(atom.mass)
S
SeeSea

翻译于 2013/06/19 14:01
 顶

1

 

防止不当的优化

queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。

使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能会造成额外的数据库查询。

所以编码时需要注意一下,如果程序开始变慢,你需要看看代码的瓶颈在哪里,是否会有一些小的优化可以帮到你。

有效使用django的queset的更多相关文章

  1. Django之DjangoAdmin

    前言: 当我们启动1个Django程序的时候,在程序的settings.py配置文件默认注册了1个名为'django.contrib.admin'的APP程序,并且配置了默认路由映射关系url(r'^ ...

  2. django之补充

    一 QuerySet类型 QuerySet类型:只和orm有关,如果一涉及数据库,就会有QuerySet类型的出现. QuerySet切片操作:QuerySet是支持切片操作的,不过不能放负数.查询集 ...

  3. 【web框架】Django

    一.什么是web框架? 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单的说,就是你用别人搭建好的舞台来做表演. 对于所有 ...

  4. 异步任务队列Celery在Django中的使用

    前段时间在Django Web平台开发中,碰到一些请求执行的任务时间较长(几分钟),为了加快用户的响应时间,因此决定采用异步任务的方式在后台执行这些任务.在同事的指引下接触了Celery这个异步任务队 ...

  5. 《Django By Example》第四章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:祝大家新年快乐,这次带来<D ...

  6. django server之间通过remote user 相互调用

    首先,场景是这样的:存在两个django web应用,并且两个应用存在一定的联系.某些情况下彼此需要获取对方的数据. 但是我们的应用肯经都会有对应的鉴权机制.不会让人家随随便便就访问的对吧.好比上车要 ...

  7. Mysql事务探索及其在Django中的实践(二)

    继上一篇<Mysql事务探索及其在Django中的实践(一)>交代完问题的背景和Mysql事务基础后,这一篇主要想介绍一下事务在Django中的使用以及实际应用给我们带来的效率提升. 首先 ...

  8. Mysql事务探索及其在Django中的实践(一)

    前言 很早就有想开始写博客的想法,一方面是对自己近期所学知识的一些总结.沉淀,方便以后对过去的知识进行梳理.追溯,一方面也希望能通过博客来认识更多相同技术圈的朋友.所幸近期通过了博客园的申请,那么今天 ...

  9. 《Django By Example》第三章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:第三章滚烫出炉,大家请不要吐槽文中 ...

随机推荐

  1. 逆卷积的详细解释ConvTranspose2d(fractionally-strided convolutions)

    1.首先先定义进行卷积的参数: 输入特征图为高宽一样的Hin*Hin大小的x 卷积核大小kernel_size 步长stride padding填充数(填充0) 输出特征图为Hout*Hout大小的y ...

  2. QGridLayout

    Help on class QGridLayout in module PyQt5.QtWidgets: class QGridLayout(QLayout) |  QGridLayout(QWidg ...

  3. ora-14400:插入的分区关键字未映射到任何分区

    参考:https://blog.csdn.net/rubychen410/article/details/5317553 出现该问题是由于: 1.为表设置了根据时间进行分区(PARTITION),而每 ...

  4. Linux系统编程之事件驱动

    通常,我们写服务器处理模型的程序时,有以下几种模型:(1)每收到一个请求,创建一个新的进程,来处理该请求:(2)每收到一个请求,创建一个新的线程,来处理该请求:(3)每收到一个请求,放入一个事件列表, ...

  5. 【MySQL 读书笔记】SQL 刷脏页可能造成数据库抖动

    开始今天读书笔记之前我觉得需要回顾一下当我们在更新一条数据的时候做了什么. 因为 WAL 技术的存在,所以当我们执行一条更新语句的时候是先写日志,后写磁盘的.当我们在内存中写入了 redolog 之后 ...

  6. MT 互联网 面试标准

    能力模型 业务理解(每项2分) java知识(每项2分) 网络知识(每项1分) 设计模式(每项3分) 数据库知识(每项2分) 框架知识(每项1分) 数据结构与算法(每项1分) 架构知识(每项3分) 操 ...

  7. application.properties

    #MySQLspring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://lo ...

  8. Oracle 12c CDB PDB 安装/配置/管理

    Oracle安装参考:https://www.cnblogs.com/zhichaoma/p/9288739.html 对于CDB,启动和关闭与之前传统的方式一样,具体语法如下:     STARTU ...

  9. [leetcode] 5.Longest Palindromic Substring-2

    想了很多方法 搞轴对称,算对称轴,偶数都高出了一堆0.5在那加加减减,最后发现在移轴之前可能就返回了. class Solution: def longestPalindrome(self, s: s ...

  10. feed.snapdo.com 病毒

    过程:安装破解office2013 使用破解工具 Microsoft toolkit 2.7 beta  1 关闭防火墙 浏览器被木马篡改:搜索引擎被篡改: 相关进程 bittorrent.exe 无 ...