提问



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


使用过Google Datastore或BigTable的人是否有任何与他们合作的好建议?

最佳参考


与传统关系数据库相比,有两个主要的事情需要习惯App Engine数据存储:



  • 数据存储区不会区分插入和更新。当您在实体上调用put()时,该实体将使用其唯一键存储到数据存储区,并且具有该键的任何内容都将被覆盖。基本上,数据存储区中的每个实体类型都像一个巨大的地图或排序列表。

  • 正如您所提到的,查询更加有限。没有加入,一开始。



要实现的关键 - 以及这两种差异背后的原因 - Bigtable基本上就像一个巨大的有序字典。因此,put操作只是设置给定键的值 - 无论该键的任何先前值如何,并且获取操作仅限于获取单个键或连续的键范围。使用索引可以实现更复杂的查询,这些索引基本上只是它们自己的表,允许您在连续范围上扫描时实现更复杂的查询。


一旦你吸收了它,你就掌握了理解数据存储的能力和局限所需的基本知识。可能看似随意的限制可能更有意义。


这里的关键是虽然这些限制是你在关系数据库中可以做的事情,但是这些相同的限制使得扩展到Bigtable旨在处理的数量级的实用性。你根本无法执行那种在纸上看起来很好但在SQL数据库中非常慢的查询。


在如何更改表示数据的方式方面,最重要的是预先计算。而不是在查询时进行连接,预先计算数据并尽可能将其存储在数据存储区中。如果要选择随机记录,请生成随机数并将其与每条记录一起存储。 这里有一整套关于这些提示和技巧的食谱编辑:食谱不再存在。[2]

其它参考1


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


在关系数据库世界中,您始终需要担心数据规范化和表结构。放弃一切。只需布置您的网页即可。全力以赴。现在看看他们。你已经2/3了。


如果您忘记了数据库大小重要且数据不应该重复的概念,那么您需要在那里重新编写3/4而您甚至不必编写任何代码!让您的观点决定您的模型。您不必采取你的对象,使它们成为二维,就像在关系世界中一样。您现在可以存储具有形状的对象。


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

其它参考2


当人们出来的时候我总是轻笑 - 这不是关系型的。我已经在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()    

其它参考3


我来自关系数据库世界然后我发现了这个数据存储区的事情。花了好几天才搞定它。我有一些发现。


您必须已经知道Datastore是按比例构建的,这是将它与RDMBS分开的事情。为了更好地使用大型数据集进行扩展,App Engine已经做了一些更改(一些意味着很多更改)。


RDBMS VS DataStore

结构的结果,
在数据库中,我们通常在表格中构建数据,在数据存储区中的行成为种类和实体。 [3]


关系结果
在RDBMS中,大多数人都采用一对一,多对一,多对多的关系,在数据存储中,因为它有无连接的东西,但我们仍然可以使用 ReferenceProperty 例如一对一关系示例。


索引结果
通常在RDMBS中,我们制作索引,如主键,外键,唯一键和索引键,以加快搜索速度并提高数据库性能。在数据存储区中,您必须为每种类型创建至少一个索引(它会自动生成您是否喜欢它),因为数据存储区会根据这些索引搜索您的实体并相信我这是最好的部分,在RDBMS中您可以使用非索引字段虽然需要一些时间,但它会。在数据存储区中,您无法使用非索引属性进行搜索。[5]


计数结果
在RDMBS中,计算(*)要容易得多,但在数据存储区中,请不要以正常的方式考虑它(是的,有一个计数函数),因为它有1000个限制,并且它将花费与实体一样多的小操作。不好但我们总是有很好的选择,我们可以使用碎片计数器。


唯一约束

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


查询结果
GAE Datatore提供了一个更好的功能LIKE(哦不!数据存储区没有LIKE关键字)SQL是GQL。 [12]


数据插入/更新/删除/选择

这是我们所有人都感兴趣的地方,因为在RDMBS中我们需要一个查询插入,更新,删除和选择就像RDBMS一样,数据存储已经放,删除,得到(不要太兴奋),因为数据存储放入或得到写入,读取,小型操作(读取数据存储调用的成本)以及数据建模开始实施的操作。您必须最小化这些操作并保持您的应用程序运行。对于减少读取操作,您可以使用Memcache。[13] [14] [15]

其它参考4


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


很好,虽然你写这篇文章来描述Objectify,但它也是我曾读过的关于appengine数据存储本身最简洁的解释之一。谢谢。


https://github.com/objectify/objectify/wiki/Concepts[16]

其它参考5


如果您以前习惯于考虑ORM映射实体那么基本上就像基于实体的数据存储区一样,谷歌的App Engine是如何工作的。对于像连接这样的东西,你可以查看参考属性。你真的不需要关心它是否使用BigTable作为后端或其他东西,因为后端是由GQL和数据存储API接口抽象的。[17]

其它参考6


我查看数据存储区的方式是,类型标识表本身,实体是表中的单独行。如果谷歌只拿出一个没有结构的大表,你可以在实体中转储你想要的任何东西。换句话说,如果实体没有绑定到某种类型,那么你几乎可以将任何结构存储到一个实体并存储在一个位置(一种没有结构的大文件,每一行都有自己的结构)。


现在回到原始评论,谷歌数据存储和bigtable是两个不同的东西,所以不要混淆谷歌数据存储与数据存储数据存储感。 Bigtable比bigquery更昂贵(主要原因我们没有使用它).Bigquery确实有正确的连接和RDBMS,如sql语言和更便宜,为什么不使用bigquery。话虽如此,bigquery确实有一些限制,取决于大小你可能会或可能不会遇到他们的数据。


另外,就数据存储方面的思考而言,我认为适当的陈述应该是根据NoSQL数据库来思考。这些天有太多可用的东西,但是当谈到谷歌产品,除了谷歌云SQL(这是mySQL),其他一切都是NoSQL。

其它参考7


根植于数据库世界,我的数据存储将是一个巨大的表(因此名称bigtable)。 BigTable是一个糟糕的例子,因为它执行了许多典型数据库可能不会执行的其他操作,但它仍然是一个数据库。除非你知道你需要构建类似Google的bigtable之类的东西,否则你很可能会使用标准数据库。他们需要这样做,因为他们一起处理大量的数据和系统,并且没有商业化的系统可以真正实现以他们能够证明他们需要完成工作的确切方式完成工作。


(重要参考:http://en.wikipedia.org/wiki/BigTable)[18]