将所有数据存储实体放在一个组中的目的是什么?
What would be the purpose of putting all datastore entities in a single group?
我已经开始处理一个使用 Google 数据存储的现有项目,其中对于某些实体类型,每个实体都分配有相同的祖先。示例:
class BaseModel(ndb.Model):
@classmethod
def create(cls, **kwargs):
return cls(parent=cls.make_key(), **kwargs)
@classmethod
def make_key(cls):
return ndb.Key('Group', cls.key_name())
class Vehicle(BaseModel):
@classmethod
def key_name(cls):
return 'vehicle_group'
所以密钥最终看起来像这样:
Key(Group, 'vehicle_group', Vehicle, 5068993417183232)
没有 'Group' 或实体 'vehicle_group' 这样的类型,但在这些文档中没关系:"note that unlike in a file system, the parent entity need not actually exist".
我从阅读中了解到,这可能具有性能优势,因为一种类型的所有实体都位于分布式数据存储区中。
但是在我看来,将所有这些实体放在一个组中会随着项目的扩展而产生问题,并且每秒一次的写入限制将适用于整个类型。该小组似乎没有任何交易原因。
项目中没有人知道为什么最初要这样做。我的问题是:
- 有谁知道这个 "xxx_group" 单一实体方案的来源
从?
- 它是否像看起来的那样?
将多个实体分组到一个实体组中至少有 2 个我能想到的优势:
- 能够在事务内执行(祖先)查询 - 事务内不允许非祖先(或跨组)查询
- 能够在同一事务中访问多个实体 - 跨组事务限制为最多 25 个实体组
1 write/second/group 限制 可能 对于某些应用程序来说根本不是可扩展性问题(例如,想想写一次读取很多类型的应用程序,或应用程序每秒 1 次写入就足够了)。
至于机制,组的(唯一)父 "entity" 密钥是 ndb.Key('Group', "xxx_group")
密钥(具有 "xxx_group" 密钥 ID)。相应的 "entity" 或其模型不需要存在(除非需要创建实体本身,但似乎并非如此)。如果需要,父键仅用于在数据存储中建立组的 "namespace"。
您可以在 Entity Keys documentation 的示例中看到某种类似的用法,请查看 Message
用法(除了 Message
只是一个 "parent" 实体祖先路径,但不是根实体):
class Revision(ndb.Model):
message_text = ndb.StringProperty()
ndb.Key('Account', 'sandy@foo.com', 'Message', 123, 'Revision', '1')
ndb.Key('Account', 'sandy@foo.com', 'Message', 123, 'Revision', '2')
ndb.Key('Account', 'larry@foo.com', 'Message', 456, 'Revision', '1')
ndb.Key('Account', 'larry@foo.com', 'Message', 789, 'Revision', '2')
...
Notice that Message is not a model class. This is because we are
using Message purely as a way to group Revisions, not to store data.
这可能是为了在组内实现强一致性查询。正如您所指出的那样,这种设计有...缺点。
如果这仅仅是参考数据(即一次读取多次写入)可能会减轻一些负面影响,但也主要使正面无效(即如果数据不经常更新,最终一致性不是问题)。
我已经开始处理一个使用 Google 数据存储的现有项目,其中对于某些实体类型,每个实体都分配有相同的祖先。示例:
class BaseModel(ndb.Model):
@classmethod
def create(cls, **kwargs):
return cls(parent=cls.make_key(), **kwargs)
@classmethod
def make_key(cls):
return ndb.Key('Group', cls.key_name())
class Vehicle(BaseModel):
@classmethod
def key_name(cls):
return 'vehicle_group'
所以密钥最终看起来像这样:
Key(Group, 'vehicle_group', Vehicle, 5068993417183232)
没有 'Group' 或实体 'vehicle_group' 这样的类型,但在这些文档中没关系:"note that unlike in a file system, the parent entity need not actually exist".
我从阅读中了解到,这可能具有性能优势,因为一种类型的所有实体都位于分布式数据存储区中。
但是在我看来,将所有这些实体放在一个组中会随着项目的扩展而产生问题,并且每秒一次的写入限制将适用于整个类型。该小组似乎没有任何交易原因。
项目中没有人知道为什么最初要这样做。我的问题是:
- 有谁知道这个 "xxx_group" 单一实体方案的来源 从?
- 它是否像看起来的那样?
将多个实体分组到一个实体组中至少有 2 个我能想到的优势:
- 能够在事务内执行(祖先)查询 - 事务内不允许非祖先(或跨组)查询
- 能够在同一事务中访问多个实体 - 跨组事务限制为最多 25 个实体组
1 write/second/group 限制 可能 对于某些应用程序来说根本不是可扩展性问题(例如,想想写一次读取很多类型的应用程序,或应用程序每秒 1 次写入就足够了)。
至于机制,组的(唯一)父 "entity" 密钥是 ndb.Key('Group', "xxx_group")
密钥(具有 "xxx_group" 密钥 ID)。相应的 "entity" 或其模型不需要存在(除非需要创建实体本身,但似乎并非如此)。如果需要,父键仅用于在数据存储中建立组的 "namespace"。
您可以在 Entity Keys documentation 的示例中看到某种类似的用法,请查看 Message
用法(除了 Message
只是一个 "parent" 实体祖先路径,但不是根实体):
class Revision(ndb.Model): message_text = ndb.StringProperty()
ndb.Key('Account', 'sandy@foo.com', 'Message', 123, 'Revision', '1') ndb.Key('Account', 'sandy@foo.com', 'Message', 123, 'Revision', '2') ndb.Key('Account', 'larry@foo.com', 'Message', 456, 'Revision', '1') ndb.Key('Account', 'larry@foo.com', 'Message', 789, 'Revision', '2')
...
Notice that Message is not a model class. This is because we are using Message purely as a way to group Revisions, not to store data.
这可能是为了在组内实现强一致性查询。正如您所指出的那样,这种设计有...缺点。
如果这仅仅是参考数据(即一次读取多次写入)可能会减轻一些负面影响,但也主要使正面无效(即如果数据不经常更新,最终一致性不是问题)。