合并缓存的GQL查询而不是使用IN

时间:2011-04-14 22:21:35

标签: python google-app-engine gql

我正在生成合并许多用户评论的Feed,因此您的Feed可能是user1 + user2 + user1000的评论,而我的可能是user1 + user2。所以我有一句话:

some_comments = Comment.gql("WHERE username IN :1",user_list)

我不能只记忆整个事情,因为每个人都有不同的提要,即使user1和user2的提要对许多观众来说都是常见的。根据{{​​3}}:

  

... IN运算符执行单独的操作   每个的基础数据存储区查询   列表中的项目。实体   返回的结果是   所有潜在的产品的交叉产品   数据存储区查询和   的去重即可。任何最多允许30个数据存储区查询   单个GQL查询。

是否有库函数来合并某些已排序和缓存的查询,或者我将不得不:

for user in user_list
  if memcached(user):
    add it to the results
  else:
    add Comment.gql("WHERE username = :1",user) to the results 
    cache it too
sort the results

(在最坏的情况下(没有缓存)我希望发送30个GQL查询比一个巨大的IN查询慢。)

2 个答案:

答案 0 :(得分:2)

没有内置任何内容可以执行此操作,但您可以自己执行此操作,但有一点需要注意:如果您执行in查询并返回30个结果,则这些将是根据您排序最低的30条记录跨所有子查询排序标准。但是,如果要从缓存的单个查询中组装结果集,则要么必须为每个用户缓存与总结果集一样多的结果(例如,30),并丢弃大部分结果,要么就是'必须为每个用户存储较少的结果,并接受有时您会丢弃一个用户的新结果,转而支持另一个用户的旧结果。

那就是说,你可以这样做:

  1. 执行memcache.get_multi以检索所有用户的缓存结果集
  2. 对于没有缓存结果集的每个用户,执行单个查询,获取所需的最多结果。使用memcache.set_multi缓存结果集。
  3. 对所有结果集执行合并连接,并将前n个结果作为最终结果集。因为用户名可能不是列表字段(例如,每个评论都有一个作者),所以您不必担心重复。
  4. 目前,in查询是按顺序执行的,因此这种方法不会比执行in查询慢,即使没有缓存任何结果。不过,这可能会在未来发生变化。如果你现在想提高性能,你可能想要使用Guido的NDB项目,它允许你并行执行所有的子查询。

答案 1 :(得分:1)

您可以使用memcache.get_multi()查看哪些用户的Feed已在memcache中。然后在原始用户列表上使用set().difference()与在memcache中找到的用户列表,以找出未检索到的用户列表。然后,最后在批处理get中从数据存储区中获取缺少的用户提要。

从那里你可以组合这两个列表,如果它不是太长,可以在内存中进行排序。如果您正在处理Ajaxy,您可以将分拣交给客户。