【问题标题】:Merging cached GQL queries instead of using IN合并缓存的 GQL 查询而不是使用 IN
【发布时间】:2011-08-05 22:30:33
【问题描述】:

我正在生成一个合并许多用户的 cmets 的提要,因此您的提要可能是 user1+user2+user1000 的 cmets,而我的可能是 user1+user2。所以我有这行:

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

我不能只对整个内容进行内存缓存,因为每个人都会有不同的提要,即使用户 1 和用户 2 的提要对许多观众来说都是通用的。根据the documentation

...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 查询要慢。)

【问题讨论】:

    标签: python google-app-engine gql


    【解决方案1】:

    您可以使用memcache.get_multi() 查看用户的哪些提要已在内存缓存中。然后在原始用户列表与在内存缓存中找到的用户列表上使用set().difference() 以找出未检索到的用户列表。然后最后以批量获取的方式从数据存储中获取丢失的用户提要。

    您可以从那里合并两个列表,如果它不是太长,则在内存中对其进行排序。如果您正在处理 Ajaxy,您可以将排序交给客户端。

    【讨论】:

      【解决方案2】:

      没有任何内置功能可以执行此操作,但您可以自己执行此操作,但需要注意一点:如果您执行 in 查询并返回 30 个结果,这些将是根据您的排序条件排序最低的 30 条记录跨越所有子查询。但是,如果您想从缓存的单个查询中组合结果集,您将不得不为每个用户缓存与总结果集一样多的结果(例如,30 个),并丢弃大部分结果,或者您将不得不为每个用户存储更少的结果,并接受有时您会丢弃来自一个用户的新结果以支持来自另一个用户的旧结果。

      也就是说,您可以这样做:

      1. 执行memcache.get_multi 以检索所有用户的缓存结果集
      2. 对于没有缓存结果集的每个用户,执行单独的查询,获取所需的最多结果。使用memcache.set_multi 缓存结果集。
      3. 对所有结果集进行合并连接,并将前 n 个结果作为最终结果集。因为用户名可能不是列表字段(例如,每条评论都有一个作者),所以您不必担心重复。

      目前,in 查询是串行执行的,因此即使没有缓存任何结果,这种方法也不会比执行in 查询慢。不过,这可能会在未来发生变化。如果您现在想提高性能,您可能需要使用 Guido 的 NDB 项目,它允许您并行执行所有子查询。

      【讨论】:

        猜你喜欢
        • 2010-11-16
        • 1970-01-01
        • 1970-01-01
        • 2015-11-15
        • 2013-12-20
        • 1970-01-01
        • 2013-05-13
        • 2014-03-29
        • 2014-05-11
        相关资源
        最近更新 更多