Google应用引擎:使用属性值作为键

时间:2015-01-24 13:08:18

标签: python google-app-engine python-2.7

我有下一个实体:

class Player(ndb.Model):
    player_id = ndb.IntegerProperty()

class TimeRecord(ndb.Model):
    time = ndb.StringProperty()

所以TimeRecord的实例是某个Player实例的子代。 如果我需要将TimeRecord的实例与某个Player放在一起,我就是这样做的:

tr = TimeRecord(parent = ndb.Key("Player", Player.query(Player.player_id == int(certain_id)).get().key.integer_id()), time = value)

此查询既昂贵又复杂。相应于doc

qry = Account.query(Account.userid == 42)

如果您确定只有一个具有该用户ID的帐户,您可能更喜欢使用userid作为密钥。 Account.get_by_id(...)比Account.query(...)。get()。

据我所知,我需要更改数据存储区的结构:

使用player_id作为播放器的键并将TimeRecord(时间)移动到播放器的属性。 player_id是唯一值。

class Player(ndb.Model):
    time = ndb.StringProperty()

问:这是一种正确的方法吗?

这类似于混合不同级别的实体继承,因为我看到每个数据应该是不同的实体。并且继承由祖先密钥实现。

UPD: 但在这种情况下,我只能为某个播放器存储一个TimeRecord值。 我需要为播放器设置一组TimeRecords。是这个问题的重复属性解决方案吗?

1 个答案:

答案 0 :(得分:2)

您提出的重新设计实质上是从关系数据库用户的POV开始,"去标准化" - 这在关系领域几乎是一个坏词,但绝对"正常" (哈哈)一旦你进入NoSQL。

如果您知道如何查询和更新内容,则反规范化会提高性能(通常)和/或存储(有时),但会牺牲一些灵活性。

但要注意权衡取舍。通常,去标准化会以更新的额外负担为代价提高查询/阅读的性能 - 这可能很好,因为通常阅读比写作更频繁,但您需要知道是否属于这种情况申请。

检查您的具体用例,我发现存储明显节省(特别是如果您可以为您的时间属性使用更专业的类型,请参阅https://cloud.google.com/appengine/docs/python/ndb/properties#Date_and_Time)并减少与后端的交互(从而提高性能)检索。它还简化了代码(简单性很好:错误风险更小,更容易进行单元测试)。

然而,如果保存新的"时间记录"对于一个玩家来说,这是一个非常频繁的需求,重复的属性变得越来越大(尽管它仍然是一个单一的交互,但在某些时候它会减慢速度;在最坏的情况下,它将会对单个实体产生影响" #39;最大尺寸,即1兆字节 - 确保,每个玩家需要数万个"时间记录"但是,根本不知道你的应用,无法判断风险是否只有可以! - )。

查询也可能是一个问题,完全取决于您的应用需求。我特别想到不平等查询。假设您需要时间记录大于'20141215-10:00:00'且小于'20141215-18:00:00'的所有玩家。唉,对重复财产的不平等查询不会为你做到这一点!也就是说,如果您查询

ndb.AND(Player.time > '20141215-10:00:00',
        Player.time < '20141215-18:00:00')

你让玩家的时间大于第一个常数,时间少于第二个 - 不一定是相同时间!这意味着查询可能会返回比您希望的更多的玩家,并且您需要过滤&#34;过滤&#34;应用程序代码中的一大堆玩家。

如果您的实体time 重复属性(例如原始的TimeRecord实体),则类似于此实体的查询将完全返回一堆感兴趣的实体(虽然如果你需要获取那些时间的玩家,那么你需要与存储后端进行另一次互动,通常是ndb.get_multi,因此,如果不了解 更多关于您应用的操作参数的话,很难预测性能影响!)。

正常化归结为通常归结为:&#34;可取性&#34;的不同方面之间的权衡取舍。 (简单,存储节省,后端交互更少,来自后端的数据量更少 - 我们甚至没有进入原子事务和异步技术的适用性! - ) - 可以进行权衡只有对应用程序的操作参数有一些深刻理解才能做到。

事实上,可能值得为每组用户部署两个或更多原型,以获得有关其执行情况的实际数据(新的云监控优惠可以帮助实现&#34 ;在选择&#34;确定&#34;之前,获取实际数据&#34;部分) (哈!)架构 - 尽管将数据从原型迁移到&#34;权威&#34;架构将产生管理费用。

如果该应用程序是一夜成名,并且突然间您每秒钟会收到数万个查询,而不是您计划的数量级别,那么性能特征可能会突然变为痛点重新设计和迁移可能是有必要的(这是一个很好的问题,当然,但仍然......)。