【问题标题】:Google App Engine Efficient Data store Read/Write Operation to Save QuotaGoogle App Engine 高效数据存储读取/写入操作以节省配额
【发布时间】:2013-08-19 20:06:11
【问题描述】:

我使用 Python 创建了一个 Google App Engine 应用程序。该应用程序处理大量用户名。

它有一个包含 50K 用户名的数据库。每个用户名都有一个唯一的哈希值。它也存储在数据存储中。

当任何应用用户提交任何用户名时。应用程序首先检查用户名是否存在于数据库中。

如果是新用户名,应用程序会为新用户名计算新的哈希值,并将名称和哈希值存储在 DataStore 中。

如果用户名已存在于数据存储中,则从数据存储中检索旧哈希。

示例代码:

class Names(db.Model):
    name = db.StringProperty(required=True)
    hash = db.StringProperty(required=True)

username = "debasish"
user_db = db.GqlQuery("SELECT * FROM Names WHERE name=:1", username)
user = user_db.get()
if user == None:
    #doesn't exist in DB..so calculate new hash for that name and store it in DB
    e = Names(name=username,hash="badasdbashdbhasbdasbdbjasbdjbasjdbasbdbasjdbjasbd")
    e.put()
else:
    #retrieve the old hash.
    self.response.out.write('{"name":"'+user.name+'","hash":"'+user.hash+'"}')            

我面临的问题是 GAE 的免费数据存储读取操作配额。它超过得太快,我的应用程序停止工作。

我也尝试过实现 memcache,就像这样,在 memcache 中添加整个数据库。但这也是失败,结果更糟糕。

def get_fresh_all(self):
    all_names = db.GqlQuery("SELECT * FROM Names")
    memcache.add('full_db', all_names, 3600)
    return all_names

那么,各位大侠能否请教一下,我是不是做错了什么?? 如何让数据存储读取操作更高效?

感谢 Adv.

【问题讨论】:

  • 您应该考虑使用“用户名”作为实体的键,然后您不需要进行查询。这比查询要快得多(操作更少)。然后你只需要Names.get_by_id(name)
  • 这就是您的应用程序的全部功能吗?如果是这样,你的限制就用完了,因为你有很多用户。只需在 2 或 3 天内拆分您的写作。 @TimHoffman 的建议将您的读取操作减少至少一半。否则,您将不得不给出一些关于您正在做的事情是否会达到您的阅读配额的指示。如果您只有很多用户访问您的网站,那么缓存(即 ndb)会有所帮助。
  • 请注意 - 来自有关 ndb 缓存的文档 - 查询不会在任何缓存中查找值。但是,如果缓存策略这样写,查询结果将被写回上下文缓存(但绝不会写回 Memcache)。所以ndb不会为重复查询提供任何好处,只会gets()

标签: python google-app-engine google-cloud-datastore


【解决方案1】:

你可以:

  • 切换到自动缓存的 NDB
  • 查询键而不是实体SELECT __key__ FROM...
  • 减少相关索引(肯定会减少写入操作,甚至可能减少读取操作)
  • 用用户名作为key_name重写所有实体并使用get_or_insert()方法
user = Names.get_or_insert("debasish", hash="badasdbashdbhasbd")

【讨论】:

  • 您绝对应该切换到 NDB,并尽可能避免进行查询(改为通过 key/id 获取实体)
【解决方案2】:

您应该只缓存 username = hash 而不是全部。另外添加一个内存缓存(这仅适用于每个实例的缓存。应该有更多帮助,只需在全局模块级别创建一个字典)。这可能会根据您的独特点击量快速增长,但您可以添加一个逻辑以仅保留某些数字。这是一个示例:

cache = {}

def get_user_hash(username):
    if username in cache:
         return cache[username]
    hash = memcache.get(username)
    if not hash:
        hash = # retrieve from db
        if not hash:
            # put to db & assign hash=new_hash

        cache[username] = hash
        memcache.set(username, hash)
    return hash

【讨论】:

    【解决方案3】:

    @Faisal 的方法应该很好用,它为查询添加了两级缓存。

    另一种选择是将用户名和哈希存储在会话中。每个会话只检查一次数据库,然后从会话变量中检索值。

    【讨论】:

      猜你喜欢
      • 2012-10-08
      • 2012-12-20
      • 1970-01-01
      • 2010-12-26
      • 1970-01-01
      • 2021-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多