龙都娱乐»Python»有效使用Django的QuerySets

有效使用Django的QuerySets

来源:oschina 发布时间:2013-06-20 阅读次数:
  对象关系映射 (ORM) 使得与SQL龙都娱乐交互更为简单,不过也被认为效率不高,比原始的SQL要慢。   要有效的使用ORM,意味着需要多少要明白它是如何查询龙都娱乐的。本文我将重点介绍如何有效使用 Django ORM系统访问中到大型的数据集。

 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)

 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)

 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!")

 当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时没有重复执行查询

 如果查询集很大的话,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)

 防止不当的优化

  queryset的cache是用于减少程序对龙都娱乐的查询,在通常的使用下会保证只有在需要的时候才会查询龙都娱乐。   使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能会造成额外的龙都娱乐查询。   所以编码时需要注意一下,如果程序开始变慢,你需要看看代码的瓶颈在哪里,是否会有一些小的优化可以帮到你。   英文原文:Using Django querysets effectively
QQ群:WEB龙都娱乐官方群(515171538),验证消息:10000
微信群:加小编微信 849023636 邀请您加入,验证消息:10000
提示:更多精彩内容关注微信公众号:全栈龙都娱乐中心(fsder-com)
网友评论(共0条评论) 正在载入评论......
理智评论文明上网,拒绝恶意谩骂 发表评论 / 共0条评论
登录会员中心
龙都娱乐