185

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

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

4

8 回答 8

150

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

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

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

一旦你吸收了这些,你就拥有了理解数据存储的功能和限制所需的基本知识。看似武断的限制可能更有意义。

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

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

于 2008-09-19T19:24:34.413 回答
43

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

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

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

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

于 2008-09-19T17:14:21.467 回答
23

当人们出来时,我总是轻笑 - 这不是关系。我在 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()    
于 2009-04-02T19:51:59.597 回答
12

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

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

RDBMS VS DataStore
结构
在数据库中,我们通常将数据构建在 Tables 中,Datastore 中的 Rows 变成Kinds 和 Entities

关系
在 RDBMS 中,大多数人遵循一对一、多对一、多对多的关系,在数据存储中,因为它有“无连接”的东西,但我们仍然可以使用“ ReferenceProperty ”实现我们的规范化“例如一对一关系示例

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

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


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

Query
GAE Datatore 提供了一个更好的功能,非常LIKE(哦,不!数据存储没有 LIKE 关键字)SQL,即GQL

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

于 2013-04-09T21:26:52.640 回答
6

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

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

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

于 2012-08-29T07:34:50.053 回答
3

如果您习惯于考虑 ORM 映射的实体,那么这基本上就是像 Google 的 App Engine 这样的基于实体的数据存储的工作方式。对于连接之类的东西,您可以查看参考属性。由于后端是由 GQL 和 Datastore API 接口抽象出来的,因此您实际上不需要担心它是使用 BigTable 作为后端还是其他东西。

于 2008-09-19T17:27:40.950 回答
0

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

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

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

于 2016-11-28T16:25:06.863 回答
-6

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

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

于 2008-09-19T17:07:17.507 回答