举例来说,Google App Engine使用Google数据存储区(而不是标准数据库)来存储数据。是否有人有使用Google数据存储区而不是数据库的提示?看来我已经训练好自己的思维,以100%地考虑直接映射到表结构的对象关系,现在很难看到任何不同的东西。我可以理解Google数据存储区的一些好处(例如性能和分发数据的能力),但是却牺牲了一些良好的数据库功能(例如联接)。
使用Google数据存储区或BigTable的人有与他们合作的任何好的建议吗?
举例来说,Google App Engine使用Google数据存储区(而不是标准数据库)来存储数据。是否有人有使用Google数据存储区而不是数据库的提示?看来我已经训练好自己的思维,以100%地考虑直接映射到表结构的对象关系,现在很难看到任何不同的东西。我可以理解Google数据存储区的一些好处(例如性能和分发数据的能力),但是却牺牲了一些良好的数据库功能(例如联接)。
使用Google数据存储区或BigTable的人有与他们合作的任何好的建议吗?
Answers:
与“传统”关系数据库相比,需要熟悉App Engine数据存储的两件事:
要实现的关键点以及这两种差异背后的原因是,Bigtable基本上就像一个巨大的有序字典。因此,放置操作仅设置给定密钥的值,而不管该密钥的任何先前值,并且提取操作仅限于提取单个密钥或连续范围的密钥。索引使更复杂的查询成为可能,这些索引基本上只是它们自己的表,使您可以将更复杂的查询实现为对连续范围的扫描。
一旦了解了这一点,便拥有了了解数据存储的功能和局限性所需的基本知识。似乎是任意的限制可能更有意义。
这里的关键是,尽管这些是对您在关系数据库中可以执行的操作的限制,但是这些相同的限制使得切实可行地扩展到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
数据存储
结构
在数据库中,我们通常将数据结构化为表,行,这些数据在数据存储中变为Kinds和Entities。
关系
在RDBMS中,大多数人的folllows一到一,多到一,多对一一对多的关系,在数据存储中,因为它没有“联接”的事情,但我们仍然可以用“实现我们的标准化的ReferenceProperty “例如一对一关系的例子。
索引
通常,在RDMBS中,我们进行主键,外键,唯一键和索引键之类的索引,以加快搜索速度并提高数据库性能。在数据存储区中,您必须为每种索引至少创建一个索引(它将自动生成您是否喜欢),因为数据存储区会根据这些索引搜索您的实体,并认为这是最好的部分,在RDBMS中,您可以使用非索引字段虽然会花费一些时间,但是会。在数据存储区中,您无法使用非索引属性进行搜索。
计数
在RDMBS中,计数(*)要容易得多,但在数据存储区中,请不要以正常方式考虑(是的,有一个计数函数),因为它有1000个Limit,并且将花费与实体一样小的操作量不好,但是我们总是有很好的选择,我们可以使用碎片计数器。
独特的限制
在RDMBS中,我们喜欢此功能,对吗?但是数据存储区有其自己的方式。您不能将属性定义为唯一的:(。
查询
GAE Datatore提供了更好的功能太多LIKE(哦,不!数据存储没有LIKE关键字),SQL是GQL。
数据插入/更新/删除/选择
这是我们所有人都感兴趣的地方,就像在RDMBS中一样,我们需要对插入,更新,删除和选择进行一次查询,就像RDBMS一样,数据存储区放置,删除,获取(不要太兴奋),因为数据存储区根据写入,读取,小型操作(数据存储调用的读取成本)放置或获取数据,这就是数据建模开始起作用的地方。您必须最小化这些操作并保持应用程序运行。对于减少读取操作,可以使用Memcache。
看一下Objectify文档。页面底部的第一条评论说:
“很不错,尽管您是为了描述Objectify而写的,但这也是我读过的Appengine数据存储库本身最简洁的解释之一。谢谢。”
如果您习惯于考虑ORM映射的实体,那么基本上就是基于实体的数据存储(例如Google的App Engine)如何工作的。对于诸如join之类的东西,您可以查看引用属性。您真的不需要担心它是将BigTable用于后端还是其他方式,因为后端是由GQL和Datastore API接口抽象的。
我看数据存储的方式是,种类本身就是表,而实体是表中的单独行。如果Google要拿出比其只有一个没有结构的大表好,那么您可以将所需的内容转储到一个实体中。换句话说,如果实体不绑定到一种实体,则您几乎可以对实体具有任何结构,并将其存储在一个位置(有点大的文件,没有结构,每行都有其自己的结构)。
现在回到原始注释,google数据存储区和bigtable是两个不同的东西,因此不要混淆google数据存储区到datastore数据存储的意义。Bigtable比bigquery昂贵(主要原因是我们没有使用它)。Bigquery确实具有适当的连接和RDBMS(例如sql语言),并且价格便宜,为什么不使用bigquery。话虽如此,bigquery确实有一些限制,具体取决于您可能会遇到或可能不会遇到的数据大小。
此外,就数据存储而言,我认为正确的陈述应该是“就NoSQL数据库而言”。这些天有太多可用的方法,但是当涉及到Google产品(除Google Cloud SQL(即mySQL)以外)时,其他一切都是NoSQL。
根植于数据库世界,对我而言,数据存储将是一个巨大的表(因此名称为“ bigtable”)。BigTable是一个不好的例子,因为它做了很多其他的事情,而典型的数据库可能做不到,但它仍然是数据库。除非您知道需要构建类似Google的“ bigtable”之类的东西,否则使用标准数据库可能会很好。他们之所以需要这样做,是因为他们正在一起处理大量的数据和系统,并且没有任何商业上可用的系统能够真正以证明他们需要完成工作的确切方式来完成这项工作。
(bigtable参考:http : //en.wikipedia.org/wiki/BigTable)