【问题标题】:How to think in data stores instead of databases?如何在数据存储而不是数据库中思考?
【发布时间】:2010-09-11 08:23:36
【问题描述】:

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

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

【问题讨论】:

  • DataSource 是一个我们正在逐步删除的旧 api - 它与数据库连接模型非常相关。 DataStore 是低级 api,它允许访问基于“原始”流的 GIS 内容方法;使用 FeatureReaders 和 FeatureWriter。
  • 现在 Google Cloud SQL 为 Google App Engine 提供关系数据库支持。如果您仍在寻找数据存储的解决方案,您可以使用Google Cloud SQL
  • 您可能想查看 Mungo 数据存储 API:bit.ly/13eSDpr

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


【解决方案1】:

与“传统”关系数据库相比,App Engine 数据存储区有两点需要习惯:

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

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

一旦您掌握了这些知识,您就具备了了解数据存储的功能和限制所需的基本知识。看似武断的限制可能更有意义。

这里的关键是,尽管这些限制是对您在关系数据库中可以执行的操作的限制,但这些限制使得扩展到 Bigtable 旨在处理的那种数量级变得切实可行。您根本无法执行在纸面上看起来不错但在 SQL 数据库中速度非常慢的那种查询。

就如何改变数据表示方式而言,最重要的是预先计算。不要在查询时进行连接,而是尽可能预先计算数据并将其存储在数据存储中。如果要选择随机记录,请生成一个随机数并将其与每条记录一起存储。这种技巧和窍门有一整本食谱here

【讨论】:

    【解决方案2】:

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

    在关系数据库世界中,您总是需要担心数据规范化和表结构。抛弃一切。只需布局您的网页。把它们都摆出来。现在看看他们。你已经有 2/3 了。

    如果您忘记了数据库大小很重要并且数据不应该重复的概念,那么您就已经是 3/4 了,您甚至不必编写任何代码!让你的观点决定你的模型。你不必再像在关系世界中那样把你的对象变成二维的。现在可以存储有形状的对象了。

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

    【讨论】:

    • 我喜欢“让你的观点决定你的模型”。少量。我认为这是来自 RDBMS 的问题,但它简化了一切。
    【解决方案3】:

    当人们提出来时,我总是轻笑——这与关系无关。我在 django 中编写了 cellectr,下面是我的模型的 sn-p。如您所见,我有由用户管理或指导的联赛。我可以从一个联赛中获取所有的经理,或者从一个给定的用户我可以返回她教练或经理的联赛。

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

    我的两便士。


    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()    
    

    【讨论】:

      【解决方案4】:

      我来自关系数据库世界,然后我发现了这个 Datastore 的东西。花了几天时间才弄明白。嗯,有一些我的发现。

      您一定已经知道 Datastore 是按比例构建的,而这正是它与 RDMBS 的区别所在。为了更好地使用大型数据集进行扩展,App Engine 进行了一些更改(有些意味着很多更改)。

      RDBMS VS 数据存储
      结构
      在数据库中,我们通常将数据构建在 Tables 中,Datastore 中的 Rows 变为Kinds and Entities

      关系
      在 RDBMS 中,大多数人遵循一对一、多对一、多对多的关系,在 Datastore 中,因为它有“无连接”的东西,但我们仍然可以使用“ReferenceProperty" 例如One-to-One Relationship Example.

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

      计数
      在 RDMBS 中,计数 (*) 要容易得多,但在数据存储中,请不要以正常方式思考它(是的,有一个计数功能),因为它具有 1000 Limit 并且它将花费与实体一样多的 small opertion这不好,但我们总是有好的选择,我们可以使用Shard Counters

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

      查询
      GAE Datatore 提供了一个更好的功能很多LIKE(哦不!数据存储没有 LIKE 关键字)SQL 是GQL

      数据插入/更新/删除/选择
      这是我们都感兴趣的地方,因为在 RDMBS 中,我们需要对插入、更新、删除和选择进行一次查询,就像 RDBMS 一样,Datastore 有 put、delete、get(不要太兴奋),因为 Datastore put 或 get 是根据 @987654331 @(阅读数据存储调用的成本)这就是数据建模发挥作用的地方。您必须最小化这些操作并保持您的应用程序运行。对于减少Read operation,您可以使用Memcache

      【讨论】:

        【解决方案5】:

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

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

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

        【讨论】:

          【解决方案6】:

          如果您习惯于考虑 ORM 映射的实体,那么这基本上就是像 Google 的 App Engine 这样的基于实体的数据存储的工作原理。对于连接之类的内容,您可以查看reference properties。由于后端是由 GQL 和 Datastore API 接口抽象出来的,因此您不必真正关心它是使用 BigTable 作为后端还是其他东西。

          【讨论】:

          • 引用属性的一个问题是它们可以快速创建 1+N 查询问题。 (拉出 1 个查询以找到 100 个人,然后为每个人进行另一个查询以获取 person.address。)
          • “引用属性”的链接已损坏,可能是由于添加了 Java 支持。试试看:code.google.com/appengine/docs/python/datastore/…
          • 链接已修复。如果/当您有足够的代表时,请随时编辑任何答案。
          【解决方案7】:

          我看待数据存储的方式是,种类识别表本身,而实体是表中的单个行。如果谷歌要拿出一张没有结构的大桌子,你可以在实体中倾倒任何你想要的东西。换句话说,如果实体不绑定到一种实体,您几乎可以对实体具有任何结构并存储在一个位置(一种没有结构的大文件,每一行都有自己的结构)。

          现在回到原来的评论,google datastore 和 bigtable 是两个不同的东西,所以不要混淆 google datastore 和 datastore 数据存储的意义。 Bigtable 比 bigquery 更昂贵(我们没有使用它的主要原因)。 Bigquery 确实有适当的连接和像 sql 语言这样的 RDBMS,而且它更便宜,为什么不使用 bigquery。话虽如此,bigquery 确实有一些限制,具体取决于您可能会遇到也可能不会遇到的数据大小。

          此外,就数据存储方面的思考而言,我认为正确的说法应该是“从 NoSQL 数据库的角度思考”。现在有太多可用的了,但是当涉及到谷歌产品时,除了谷歌云 SQL(即 mySQL)之外,其他一切都是 NoSQL。

          【讨论】:

            【解决方案8】:

            扎根于数据库世界,对我来说数据存储将是一个巨大的表(因此得名“bigtable”)。 BigTable 是一个不好的例子,因为它做了很多典型数据库可能做不到的其他事情,但它仍然是一个数据库。除非您知道您需要构建类似 Google 的“bigtable”之类的东西,否则您可能会使用标准数据库。他们需要这样做,因为他们要一起处理大量的数据和系统,而且没有任何商业可用的系统可以真正按照他们可以证明他们需要完成这项工作的方式来真正完成这项工作。

            (大表参考:http://en.wikipedia.org/wiki/BigTable

            【讨论】:

            • 这个问题专门与使用 Bigtable 的 Google App Engine 相关;使用关系数据库不是一种选择。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-24
            • 2010-10-27
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多