0

我的 Python 高复制数据存储应用程序需要一个包含 100,000 到 1,000,000 个条目的大型查找表。我需要能够为某些方法提供代码,该方法将返回与该代码关联的值(如果没有关联,则返回 None)。例如,如果我的表包含可接受的英语单词,那么我希望函数在找到该单词时返回 True,否则返回 False(或 None)。

我当前的实现是为每个表条目创建一个无父实体,并让该实体包含任何关联的数据。我将该实体的数据存储键设置为与我的查找代码相同。(我将所有实体放入它们自己的命名空间以防止任何键冲突,但这对于这个问题不是必需的。)然后我只需在代码上调用 get_by_key_name() 并获取相关数据。

问题是我无法在事务期间访问这些实体,因为我试图跨越实体组。回到我的例子,假设我想对聊天会话中使用的所有单词进行拼写检查。我可以访问聊天中的所有消息,因为我会给他们一个共同的祖先,但我无法访问我的单词表,因为那里的条目是无父的。我必须能够在事务期间引用该表。

请注意,我的查找表是固定的,或者很少更改。这再次与拼写检查示例匹配。

一种解决方案可能是在一个事务期间加载聊天会话中的所有单词,然后对它们进行拼写检查(保存结果),然后启动第二个事务,对保存的结果进行拼写检查。但这不仅效率低下,而且可能已将聊天会话添加到事务之间。这似乎是一个笨拙的解决方案。

理想情况下,我想告诉 GAE 查找表是不可变的,因此我应该能够在不抱怨事务中跨越实体组的情况下对其进行查询。但是,我看不出有任何方法可以做到这一点。

将表条目存储在内存缓存中很诱人,但这也有问题。这是大量的数据,但更麻烦的是,如果 GAE 启动了一个 memcache 条目,我将无法在事务期间重新加载它。

有谁知道大型全局查找表的合适实现?

请理解,我不是在寻找拼写检查网络服务或类似的东西。我使用单词查找作为示例只是为了清楚地说明这个问题,并且我希望为任何类型的大型查找表提供通用解决方案。

4

2 回答 2

1

首先,如果您相信命名空间将有助于避免键冲突,那么是时候退后一步了。键由实体种类、命名空间、名称或 id 以及实体可能具有的任何父项组成。两种不同的实体类型具有相同的名称或 ID 是完全有效的。因此,如果您有一个LookupThingy匹配的对象,并且通过指定唯一名称创建了每个成员,则该键不会与其他任何内容发生冲突。

至于对事务中的无父查找表进行相当于拼写检查的挑战,是否可以将查找表保留在代码中?

或者你能想出一个更接近你需要的类比吗?激发在事务中进行查找的需要?

于 2011-09-17T03:46:07.917 回答
1

如果可以,请尝试将数据放入实例内存中。如果它不适合实例内存,您可以使用一些选项。

您可以将数据存储在随应用程序上传的资源文件中,如果它只是不经常更改,并从磁盘访问它。这假设您可以构建一个允许轻松查找磁盘的数据结构 - 实际上,您正在实现自己的基于磁盘的只读表。

同样,如果它太大而不适合作为静态资源,您可以采用与上述相同的方法,但将数据存储在 blobstore 中。

如果您的数据绝对必须在数据存储中,您可能需要模拟自己的读取-修改-写入事务。将“修订”属性添加到您的记录中。要修改它,获取记录(在事务之外),执行所需的更改,然后在事务内部,再次获取它以检查修订值。如果没有更改,请在您自己的记录上增加修订并将其存储到数据存储中。

请注意,底层 RPC 层在理论上确实支持多个独立事务(和非事务操作),但是 API 目前没有公开任何从事务中访问它的方法,除了可怕的(我的意思是非常可怕的)黑客,很遗憾。

最后一个选择:您可以运行配置有更多内存的后端,公开“SpellCheckService”,并从前端对其进行 URLFetch 调用。请记住,内存中的速度总是比任何基于磁盘的选项快得多。

于 2011-09-19T04:33:01.933 回答