例如,Google App Engine使用Google Datastore而不是标准数据库来存储数据.有没有人有使用Google数据存储而不是数据库的提示?似乎我已经训练了我的思想,在直接映射到表结构的对象关系中100%思考,现在很难看到任何不同的东西.我可以理解Google数据存储区的一些好处(例如性能和分发数据的能力),但牺牲了一些好的数据库功能(例如连接).
与Google Datastore或BigTable合作过的人是否有任何与他们合作的好建议?
与"传统"关系数据库相比,关于App Engine数据存储区有两个主要的习惯:
数据存储区不会区分插入和更新.当您在实体上调用put()时,该实体将使用其唯一键存储到数据存储区,并且具有该键的任何内容都将被覆盖.基本上,数据存储区中的每个实体类型都像一个巨大的地图或排序列表.
正如您所提到的,查询更加有限.没有加入,一开始.
要实现的关键 - 以及这两种差异背后的原因 - 是Bigtable基本上就像一个巨大的有序字典.因此,put操作只是设置给定键的值 - 无论该键的任何先前值如何,并且获取操作仅限于获取单个键或连续的键范围.使用索引可以实现更复杂的查询,这些索引基本上只是它们自己的表,允许您在连续范围上扫描时实现更复杂的查询.
一旦掌握了这些知识,您就拥有了解数据存储区功能和限制所需的基本知识.可能看似随意的限制可能更有意义.
这里的关键是虽然这些限制是你在关系数据库中可以做的事情,但是这些相同的限制使得扩展到Bigtable旨在处理的那种规模的实用性.您根本无法执行在纸上看起来很好但在SQL数据库中非常慢的查询类型.
在如何更改表示数据的方式方面,最重要的是预先计算.而不是在查询时进行连接,而是预先计算数据并尽可能将其存储在数据存储区中.如果要选择随机记录,请生成随机数并将其与每条记录一起存储.有这些种类的技巧和窍门的整个食谱这里编辑:菜谱是不再存在.
我一直在进行思维转换的方式是完全忘记数据库.
在关系数据库世界中,您始终需要担心数据规范化和表结构.放弃一切.只需布置您的网页即可.全力以赴.现在看看他们.你已经2/3了.
如果你忘记了数据库大小很重要且数据不应该重复的概念,那么你就是3/4而你甚至不需要编写任何代码!让您的观点决定您的模型.你不必像对待世界一样把你的物体变成二维.您现在可以存储具有形状的对象.
是的,这是对苦难的简化解释,但它帮助我忘记了数据库,只是做了一个应用程序.到目前为止,我已经使用这种理念制作了4个App Engine应用程序,还有更多应用程序.
当人们出来时我总是轻笑 - 这不是关系型的.我在django写过cellectr,下面是我模型的片段.正如您将看到的,我有一些由用户管理或指导的联赛.我可以从一个联盟获得所有的经理,或者从一个给定的用户我可以返回她教练或经理的联盟.
仅仅因为没有特定的外键支持并不意味着您不能拥有具有关系的数据库模型.
我的两便士.
class League(BaseModel): name = db.StringProperty() managers = db.ListProperty(db.Key) #all the users who can view/edit this league coaches = db.ListProperty(db.Key) #all the users who are able to view this league def get_managers(self): # This returns the models themselves, not just the keys that are stored in teams return UserPrefs.get(self.managers) def get_coaches(self): # This returns the models themselves, not just the keys that are stored in teams return UserPrefs.get(self.coaches) def __str__(self): return self.name # Need to delete all the associated games, teams and players def delete(self): for player in self.leagues_players: player.delete() for game in self.leagues_games: game.delete() for team in self.leagues_teams: team.delete() super(League, self).delete() class UserPrefs(db.Model): user = db.UserProperty() league_ref = db.ReferenceProperty(reference_class=League, collection_name='users') #league the users are managing def __str__(self): return self.user.nickname # many-to-many relationship, a user can coach many leagues, a league can be # coached by many users @property def managing(self): return League.gql('WHERE managers = :1', self.key()) @property def coaching(self): return League.gql('WHERE coaches = :1', self.key()) # remove all references to me when I'm deleted def delete(self): for manager in self.managing: manager.managers.remove(self.key()) manager.put() for coach in self.managing: coach.coaches.remove(self.key()) coaches.put() super(UserPrefs, self).delete()
我来自关系数据库世界,然后我找到了这个数据存储的东西.花了好几天才搞定它.以及我的一些发现.
您必须已经知道Datastore是按比例构建的,这是将它与RDMBS分开的事情.为了更好地使用大型数据集进行扩展,App Engine已经做了一些更改(一些意味着很多更改).
RDBMS VS DataStore
结构
在数据库中,我们通常在Tables,Rows中构建数据,在Datastore中它成为Kinds和Entities.
关系
在RDBMS中,大多数人的folllows一到一,多到一,多对一一对多的关系,在数据存储中,因为它没有"联接"的事情,但我们仍然可以用"实现我们的标准化的ReferenceProperty "例如一对一的关系示例.
索引
通常在RDMBS中,我们制作索引,如主键,外键,唯一键和索引键,以加快搜索速度并提高数据库性能.在数据存储区中,您必须为每种类型创建至少一个索引(它会自动生成您是否喜欢它),因为数据存储区会根据这些索引搜索您的实体并相信我这是最好的部分,在RDBMS中您可以使用非索引字段虽然需要一些时间,但它会.在数据存储区中,您无法使用非索引属性进行搜索.
计数
在RDMBS中,计算(*)要容易得多,但在数据存储区中,请不要以正常的方式考虑(是的,有一个计数函数),因为它有1000个限制,它将花费与实体一样多的小操作不好,但我们总是有很好的选择,我们可以使用碎片计数器.
独特的约束
在RDMBS中,我们喜欢这个功能吗?但Datastore有自己的方式.你不能将属性定义为唯一:(.
Query
GAE Datatore提供了一个更好的功能LIKE(哦不!数据存储区没有LIKE关键字)SQL是GQL.
数据插入/更新/删除/选择
我们都感兴趣的地方,因为在RDMBS中我们需要一个查询,如插入,更新,删除和选择就像RDBMS一样,数据存储已经放,删除,得到(不要太兴奋)因为数据存储放入或获取写入,读取,小操作(数据存储调用的读取成本)以及数据建模开始实施的操作.您必须最小化这些操作并保持您的应用程序运行.对于减少读取操作,您可以使用Memcache.
看看Objectify文档.页面底部的第一条评论说:
"很好,虽然你写这篇文章来描述Objectify,但它也是我读过的关于appengine数据存储本身最简洁的解释之一.谢谢."
https://github.com/objectify/objectify/wiki/Concepts