寻找Google App Engine的非规范化建议

时间:2011-02-06 14:27:09

标签: google-app-engine database-design google-cloud-datastore

我正在研究一个将在GAE上运行的系统,该系统将包含多个相关实体,我不确定存储数据的最佳方式。这篇文章是对可能有类似经历的其他人的建议的请求....

系统将拥有用户,包含个人资料数据和图像。这些用户将能够创建“事件”并向其添加日记条目。出于系统的目的,“事件”可能在其中包含1或2个日记帐分录,并且任何超过10个的事件都可能永远不会发生。其他用户也可以为用户的条目添加评论,其中流行的评论可能有数百甚至数千条评论。当随机访问者使用该系统时,他们应该能够看到最新的事件(最新的事件,由其中包含最新日记条目的人定义),按标签搜索以及非常有效的基本文本搜索。然后,在选择要查看的事件时,应显示所有日记帐分录和所有用户评论,其中包含用户图像和评论。用户还应该拥有一种自我管理页面,以查看/修改/删除他们的事件,以及查看/修改/删除他们对其他事件所做的评论。因此,在普通的RDBMS上执行所有这些操作只会查询几个表中的一些大连接。在GAE上,它显然需要以不同的方式工作。以下是我对实体设计的初步想法:

  • 事件实体 - id,name,timstamp,list 标签属性,查看次数, creator的用户名,创建者的个人资料 图像ID,日记帐分录数量 它包含,总评论数 它包含,包含日记条目的最后更新的时间戳,搜索索引词的列表属性(从包含的日记条目中的文本构建/更新)
  • JournalEntry实体 - 时间戳, 期刊文本,活动名称, creator的用户名,创建者的个人资料 图片ID,评论的列表属性 (包含评论者用户名和 图片ID)
  • 用户实体 - 用户名,密码哈希,电子邮件,订阅事件的列表属性,创建日期的时间戳,图像ID,发布的评论数,创建的事件数,创建的日记条目数,上次日记活动的时间戳
  • UserComment实体 - 用户名,评论的事件ID,
  • 评论的事件标题
  • TagData实体 - 标记名称,带有标记的事件计数

所以,我想听听这里的人们对设计的看法,以及应该做些什么改变来帮助它很好地扩展。谢谢!

1 个答案:

答案 0 :(得分:8)

  • 不是将Event.id存储为属性,而是使用自动嵌入在每个实体key中的ID,或在创建实体时为其设置唯一key names
  • 您可以使用很多选项来建模EventJournalEntry之间的关系:您可以使用ReferenceProperty,父级JournalEntries可以使用Events和使用祖先查询检索它们,或者您可以在JournalEntry上存储Event个键ID或名称列表,并使用关键查询批量检索它们。使用逼真分布的虚拟数据尝试一些事情,并使用appstats查看效果最佳的内容。
  • UserComment引用Event,而JournalEntry引用UserComments列表,这有点令人困惑。 UserCommentJournalEntry之间是否存在关系?或仅在UserCommentEvent之间?
  • 坚持如此多的罪名是昂贵的。当我发布评论时,您将编写新的UserComment实体,并更新我的User实体和JournalEntry实体以及Event实体。您期望每UserComments Event的数量使得将所有内容都包含在同一个实体组中是不明智的,这意味着您无法以事务方式执行这些写操作,因此您将按顺序执行这些操作,以及实体可能存储在不同的网络节点上,使整个操作变慢;而且你也会对一致性问题持开放态度。如果没有这些计数,你可以考虑将其他人存储在memcache中吗?
  • 当您从数据存储区中获取Event时,您实际上并不关心其搜索索引字列表,并且从协议缓冲区中检索和反序列化它们会产生成本。您可以通过将每个Event的搜索索引单词拆分为单独的子EventIndex实体来解决此问题。然后,您可以在搜索字词上查询EventIndex,仅获取与您的搜索匹配的EventIndex EventIndexes个密钥,并使用Events导出相应的key.parent()个密钥,并按键获取Events,从不支付搜索索引词列表的检索或反序列化。 Brett Slatkin在14:35解释了这个策略here
  • 如果您快速连续查看任何Event.viewCount的大量观看次数,则更新Event将失败,因此您应该尝试使用计数器sharding
祝你好运,并通过尝试解决问题告诉我们你学到了什么。