AppEngine中按键查询和遍历对象

0 投票
3 回答
1081 浏览
提问于 2025-04-17 02:28

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 是一个很好的工具,可以帮助你发现和诊断这类性能问题。

撰写回答