说明在 Google Datastore (GAE) 上读/写的性能注意事项?

Posted

技术标签:

【中文标题】说明在 Google Datastore (GAE) 上读/写的性能注意事项?【英文标题】:Explanation of performance considerations of read/write on Google Datastore (GAE)? 【发布时间】:2011-02-17 19:38:25 【问题描述】:

我很难理解 Google App Engine 数据存储区的机制。 我想了解其中的机制,以便以最佳方式为数据库构建数据库。

鉴于下面的示例,有人可以帮助我吗:

    优化数据库结构 了解在给定结构的情况下读取和写入的性能

示例: 假设我有 N 个棒球运动员,每个人都有一个唯一的 ID。 我想每天记录每个球员击出的本垒打(存储“每日总本垒打”属性),并在击出本垒打时增加它。 因此,随着时间的增加,我想展示 X 年来每位棒球运动员每天的本垒打图表。

Player 1
1/21/2011 - 2 homeruns
1/22/2011 - 0 homeruns
1/23/2011 - 1 homeruns

阅读要求:阅读某位球员最近 5 年的每日“本垒打”数据?

写入要求:增加某个棒球运动员的每日全垒打数。

我很想了解如何构建数据以及读写机制?这个简单的存储任务会扩展吗?谢谢大家。

【问题讨论】:

你打算用 Python 还是 Java 开发? 我想知道编程语言与这个问题有什么关系 【参考方案1】:

我会用这样的一对多关系来模拟您的需求:

class Player(db.Model):
  name = db.StringProperty()

class DailyHomeruns(db.Model):
  date = db.DateProperty()
  counter = db.IntegerProperty()
  player = db.ReferenceProperty(Player)

要检索给定Player 的所有DailyHomeruns,您可以这样做:

daily_homeruns = DailyHomeruns.all().filter('player =', player)
                                    .filter('date >', date_start)
                                    .filter('date <=', date_end)
                                    .order('date')

阅读要求

Google App Engine 性能查询 随结果集的大小缩放 而不是数据集的大小。

这意味着,如果您的 过去 5 年本垒打查询 集平均包含 800 个实体 *,则无论搜索超过一千个实体还是一百万个实体,此查询的执行结果都是相同的实体。

写作要求: Google App Engine 中的写入速度很慢,但您的场景似乎很简单,我没有看到任何可能的争用/超时问题; 毕竟,您只需要连续更新DailyHomeruns,每天将计数器递增几次。

其他想法: 如果您需要计算一些统计数据,例如给定Player 的本垒打总数,甚至不要考虑为此目的使用GQL,因为它不提供任何聚合函数à la SQL。 相反,您必须预先设计数据库,定义一个模型来存储每位玩家的本垒打总数。 使用transactions API,每次增加DailyHomeruns 时,您都需要增加该播放器的 TotalHomeruns 实体。

* 我估计每周 3 场比赛,持续 52 周,每 5 年相乘

【讨论】:

【参考方案2】:

这个问题没有单一的答案。数据存储非常低级,由您来创建正确的索引和预处理数据,以便可以更快地检索它。此外,根据对同一实体的并发访问,您必须使用非常有创意的东西,例如 http://code.google.com/appengine/articles/sharding_counters.html

我可以建议您观看两场 Google I/O 会议以帮助您入门 http://sites.google.com/site/io/under-the-covers-of-the-google-app-engine-datastore 为您提供关于一切如何工作以及为什么以这种方式完成的低级别概述(直至扇区如何写入磁盘)

然后http://sites.google.com/site/io/building-scalable-web-applications-with-google-app-engine 将向您展示如何在现实世界的应用程序中使用这些低级的东西。

还有一个为常见问题提供了其他解决方案 http://www.google.com/events/io/2009/sessions/BuildingScalableComplexApps.html - 很高兴让您对数据存储限制的新型解决方案敞开心扉。

【讨论】:

顺便说一句,分片计数器用于每秒更改数次的属性。对每个更改使用简单写入将达到单个实体的写入限制。 @Peter Sharded 计数器对于计算本垒打来说是不必要的,除非你有一个棒球运动员可以在很长一段时间内击打超过一秒。 为了澄清,我添加了分片计数器作为限制(同一实体上的并发事务)和解决方案的示例。与本垒打计数用例没有直接关系。

以上是关于说明在 Google Datastore (GAE) 上读/写的性能注意事项?的主要内容,如果未能解决你的问题,请参考以下文章

Google App Engine Datastore 集成测试

Google App Engine Datastore 中的索引和索引条目限制

GAE DataStore 如何支持事务?

如何确保 GAE 上的 MemCache 和 Datastore 之间的一致性?

在 Google App Engine Datastore (python 2.7) 中存储 lambda 函数

如何在 Datastore GAE Python 中定义键名?