My Python High Replication Datastore应用程序需要100000到1000000个条目的大型查找表。我需要能够为某个方法提供一个代码,该方法将返回与该代码关联的值(如果没有关联,则返回None(。例如,如果我的表中包含可接受的英语单词,那么如果找到该单词,我希望函数返回True,否则返回False(或None(。
我目前的实现是为每个表条目创建一个无父实体,并使该实体包含任何关联的数据。我将该实体的数据存储键设置为与查找代码相同。(我将所有实体放入它们自己的命名空间中,以防止任何键冲突,但这对这个问题来说并不重要。(然后,我只需对代码调用get_by_key_name((,就可以获得相关的数据。
问题是,我无法在事务过程中访问这些实体,因为我试图跨越实体组。所以回到我的例子,假设我想拼写检查聊天会话中使用的所有单词。我可以访问聊天中的所有消息,因为我会给它们一个共同的祖先,但我无法访问我的单词表,因为那里的条目是无父母的。我必须能够在交易过程中引用该表。
请注意,我的查找表是固定的,或者很少更改。同样,这与拼写检查示例相匹配。
一种解决方案可能是在一次交易中加载聊天会话中的所有单词,然后对其进行拼写检查(保存结果(,然后启动第二次交易,根据保存的结果进行拼写检查。但这不仅效率低下,而且可能会在交易之间添加聊天会话。这似乎是一个笨拙的解决方案。
理想情况下,我想告诉GAE,查找表是不可变的,因此我应该能够对它进行查询,而不会抱怨它在事务中跨越实体组。然而,我看不出有什么办法可以做到这一点。
将表项存储在memcache中很诱人,但这也存在问题。这是大量的数据,但更麻烦的是,如果GAE引导出一个memcache条目,我将无法在事务期间重新加载它。
有人知道大型全局查找表的合适实现吗?
请理解,我不是在寻找拼写检查网络服务或类似的东西。我以单词查找为例,只是为了让这个问题变得清楚,我希望能为任何类型的大型查找表找到一个通用的解决方案。
如果可以,请尝试将数据放入实例内存中。如果它不适合实例内存,您可以选择几个选项。
您可以将数据存储在随应用程序上传的资源文件中(如果该文件很少更改(,并在磁盘外访问该文件。这假设您可以构建一个允许轻松查找磁盘的数据结构——实际上,您正在实现自己的基于只读磁盘的表。
同样,如果它太大,无法作为静态资源使用,可以采用与上面相同的方法,但将数据存储在blobstore中。
如果数据绝对必须在数据存储中,则可能需要模拟自己的读-修改-写事务。将"修订"属性添加到您的记录中。要修改它,请获取记录(在事务外部(,执行所需的更改,然后在事务内部,再次获取它以检查修订值。如果它没有更改,请在您自己的记录上增加修订并将其存储到数据存储中。
请注意,底层RPC层理论上确实支持多个独立事务(和非事务操作(,但API目前没有公开任何从事务中访问这些事务的方法,不幸的是,除了可怕的(我指的是非常可怕的(黑客攻击。
最后一个选择是:你可以运行一个配备更多内存的后端,暴露一个"SpellCheckService",并从前端对其进行URLFetch调用。记住,内存永远比任何基于磁盘的选项都快得多。
首先,如果您相信命名空间将有助于避免密钥冲突,那么是时候退一步了。键由实体种类、命名空间、名称或id以及实体可能具有的任何父级组成。两种不同的实体类型具有相同的名称或id是完全有效的。因此,如果你有一个匹配的LookupThingy
,并且通过指定一个唯一的名称创建了每个成员,那么密钥就不会与其他任何东西冲突。
至于在事务中对未租用的查找表进行相当于拼写检查的挑战,是否可以将查找表保存在代码中?
或者你能想出一个更接近你需要的类比吗?促使需要在事务中进行查找的因素?