如何在数据存储而不是数据库中思考?

例如,Google App Engine使用数据存储而不是数据库来存储数据。 有谁有使用数据存储,而不是数据库的任何提示? 看起来我已经训练了自己的思想去思考100%直接映射到表结构的对象关系,现在很难看到任何不同的东西。 我可以理解数据存储的一些好处(例如,性能和分发数据的能力),但是牺牲了一些好的数据库function(例如连接)。

有没有人像BigTable一样使用数据存储有什么好的build议来与他们合作?

与传统的关系型数据库相比,App Engine数据存储有两个主要的用处:

  • 数据存储不区分插入和更新。 在实体上调用put()时,该实体将以其唯一键被存储到数据存储中,并且具有该键的任何内容都将被覆盖。 基本上,数据存储中的每种实体types都像一个巨大的地图或sorting列表。
  • 如你所说,查询是非常有限的。 没有join,一开始。

要认识到的关键是这些差异背后的原因是Bigtable基本上就像一个巨大的有序字典。 因此,put操作只是为给定的键设置值,而不pipe该键的任何以前的值如何,并且提取操作仅限于获取单个键或连续范围的键。 使用索引可以实现更复杂的查询,索引基本上只是自己的表,允许您在连续的范围内执行更复杂的查询作为扫描。

一旦吸收了这些知识,就可以获得理解数据存储的function和限制的基本知识。 可能看似武断的限制可能更有意义。

关键在于,虽然这些限制了您在关系数据库中可以执行的操作,但是这些限制是可以扩展到Bigtabledevise要处理的程度的。 你只是不能执行那种在纸上看起来不错的查询,但在SQL数据库中却很慢。

就如何改变你如何表示数据而言,最重要的是预先计算。 而不是在查询时间进行连接,预先计算数据并尽可能将其存储在数据存储中。 如果你想select一个随机logging,生成一个随机数并将其与每条logging一起存储。 这里有一个这样的提示和技巧的食谱编辑:食谱不再存在。

我一直在思考转换的方式是完全忘记数据库。

在关系数据库世界里,你总是不得不担心数据规范化和你的表结构。 放弃一切。 只是布局你的网页。 把他们全部弄清楚。 现在看看他们。 你已经2/3了。

如果你忘记了数据库大小的重要性和数据不应该重复的概念,那么你在那里3/4,你甚至不必写任何代码! 让你的意见决定你的模型。 就像在关系世界里一样,你不需要把你的对象变成二维的。 您现在可以用形状存储对象。

是的,这是一个简单的解释,但它帮助我忘记了数据库,只是做一个应用程序。 到目前为止,我已经使用这一理念制作了4款App Engine应用程序,还有更多。

当人们走出来的时候,我总是轻笑 – 这不是关系。 我已经在django写了cellar,下面是我的模型的一个片段。 你会看到,我有由用户pipe理或指导的联赛。 我可以从一个联盟得到所有的经理人,或者从一个特定的用户,我可以返回她的教练或经理人的联赛。

仅仅因为没有特定的外键支持并不意味着你不能拥有一个关系的数据库模型。

我的两个便士


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是按比例构build的,这是将其与RDMBS分开的东西。 为了更好地利用大型数据集进行扩展,App Engine已经做了一些改变(一些意味着很多改变)。

RDBMS VS DataStore
结构体
在数据库中,我们通常将表格中的数据结构化,在数据存储区中的行就成为种类和实体 。

关系
在RDBMS中,大多数人都是一对一,多对一,多对多的关系,在数据存储中,由于它有“无连接”的东西,但是我们仍然可以使用“ ReferenceProperty ”来实现我们的规范化。例如一对一关系示例 。

索引
通常在RDMBS中,我们使用主键,外键,唯一键和索引键来加速search,提高数据库性能。 在数据存储中,每种types都必须至less创build一个索引(无论您是否喜欢它,它都会自动生成 ),因为数据存储在这些索引的基础上search您的实体并相信我是最好的部分,在RDBMS中,您可以使用非索引字段虽然需要一些时间,但它会。 在数据存储中,您不能使用非索引属性进行search。

计数
在RDMBS中,计数(*)要容易得多,但是在数据存储中,请不要以正常的方式来思考(是的,这里有一个计数函数),因为它有1000个限制 ,它的成本和实体一样小不好,但我们总是有不错的select,我们可以使用碎片计数器 。

独特的约束
在RDMBS中,我们喜欢这个function吗? 但Datastore有自己的方法。 你不能将属性定义为唯一:(。

询问
GAE Datatore提供了一个更好的functionLIKE (哦不!数据存储没有LIKE关键字)SQL是GQL 。

数据插入/更新/删除/select
在RDMBS中,我们需要一个查询插入,更新,删除和select,就像RDBMS一样,数据存储已经放置,删除,得到(不要太激动),因为数据存储在写入,阅读,小型操作 (读取数据存储调用的成本 )以及数据build模开始实施的地方。 你必须尽量减less这些操作,并保持你的应用程序运行。 为了减less读取操作,您可以使用Memcache 。

看看Objectify文档。 页面底部的第一条评论说:

“很好,虽然你写这个来描述Objectify,但它也是我阅读过的appengine数据存储最简洁的解释之一,谢谢。

https://github.com/objectify/objectify/wiki/Concepts

如果您习惯于考虑ORM映射的实体,那么基本上像Google的App Engine这样基于实体的数据存储是如何工作的。 对于像连接这样的东西,你可以看引用属性 。 由于后端由GQL和Datastore API接口提取,因此您不必担心它是否将BigTable用于后端或其他内容。

我看数据存储的方式是,种类标识表本身,而实体是表中的单个行。 如果谷歌要比它只有一张没有结构的大桌子更好,那么你可以把任何你想要的东西放到一个实体中。 换句话说,如果实体没有绑定到某种types,那么几乎可以有任何实体的结构并存储在一个位置(一种没有结构的大文件,每行都有自己的结构)。

现在回到原来的评论,谷歌datastore和bigtable是两个不同的东西,所以不要混淆谷歌数据存储到数据存储的数据存储感。 Bigtable比bigquery更昂贵(主要原因是我们没有去用它)。 Bigquery确实有适当的连接和RDBMS像SQL语言和便宜,为什么不使用bigquery。 这就是说,bigquery确实有一些限制,取决于您可能会遇到或可能不会遇到的数据大小。

另外就数据存储方面的思考而言,我认为恰当的说法就是“用NoSQL数据库来思考”。 这些日子里有太多可用的,但当涉及谷歌产品,除谷歌云SQL(这是mySQL)一切是NoSQL。

根植于数据库世界,对我来说一个数据存储将是一个巨大的表(因此名称“bigtable”)。 BigTable是一个不好的例子,虽然它做了很多其他的事情,一个典型的数据库可能不会做,但它仍然是一个数据库。 机会是除非你知道你需要build立像谷歌的“bigtable”,你可能会用标准的数据库罚款。 他们需要这样做,因为他们一起处理疯狂的数据和系统数量,没有一个商业上可用的系统能够真正做到这一点,他们可以certificate他们需要完成这项工作。

(bigtable参考: http : //en.wikipedia.org/wiki/BigTable )