AppEngine中按键查询和遍历对象
AppEngine的文档提到:“返回键的查询比返回完整实体的查询速度更快,消耗的CPU也更少。”
在这两种方式中,哪一种更适合从数据存储中获取并遍历多个对象呢?
query_keys = Person.all(keys_only=True)
query_keys.filter('name = ', person_name)
query_keys.order("__key__")
people = db.get(query_keys)
for p in people:
#read properties of the person object
print p.name
与
query = Person.all()
query.filter('name = ', person_name)
query.order("__key__")
for p in people:
#read properties of the person object
print p.name
3 个回答
1
只查询键的查询只会给你键,而不是包含属性的实体。在第一个例子中,p
不会有 .name
这个属性。而且,键的顺序是隐含的。如果你想要实体的属性,单纯的键查询就不合适了;你需要直接查询这个实体。目前没有办法只获取部分属性,所以在设计数据时要考虑到这一点。
这里有第三种选择,你可能会觉得它更易读,也可能觉得不那么好。它的性能和你的第二段代码是一样的。
people = Person.gql("WHERE name=:1", person_name)
for person in people:
print person.name
无论你使用这种方法还是你的第二段代码,直接查询实体会比先查询键再获取对应实体要快。
1
既然你反正要读取完整的实体,那么第二种方法至少不会比第一种慢。其实可能会更快,因为它的API调用次数更少。
2
一个普通的查询基本上就是你第一个代码片段所做的操作,不过是在一个单独的远程过程调用(RPC)中完成的。如果你需要获取实体数据,直接请求这些数据会更有效率,而不是先请求键值再自己去获取实体。
在效率方面,有一点需要注意,就是在遍历查询对象时。这样做会导致底层的RPC层每次从数据存储中批量获取20条结果,这样会产生很多不必要的RPC调用。如果你知道需要多少结果,应该在查询上调用 fetch()
方法(比如 results = Person.all().filter('name =', 'Joe').fetch(100)
),这样只会执行一次RPC。
Appstats 是一个很好的工具,可以帮助你发现和诊断这类性能问题。