生活没有JOINs …理解和常见的做法

很多“BAW”(大屁股网站)正在使用数据存储和检索技术,这些技术依赖于具有索引的巨大表格,并且使用不会/不能在查询中使用JOIN的查询(BigTable,HQL等)处理可扩展性和分片数据库。 当你有很多非常相关的数据时,这是如何工作的?

我只能推测,这个join的大部分都是在应用程序方面完成的,但是不会开始变得昂贵? 如果你不得不对几个不同的表进行几个查询来获得信息进行编译呢? 是不是碰到数据库,多次开始比首先使用联接更昂贵? 我想这取决于你有多less数据?

对于通常可用的ORM,他们如何倾向于处理无法使用连接? 在今天使用率很高的ORM中是否有这种支持? 或者大多数需要处理这个级别的数据的项目往往会自行推出?

所以这不适用于我目前正在进行的任何项目,但现在我已经有好几个月的时间了,我只能猜测“最佳实践”是什么。 我从来没有必要在我的任何项目中解决这个问题,因为他们从未达到需要的规模。 希望这个问题也能帮助其他人。

正如下面有人所说,没有联接,ORM“不工作”。 是否有其他数据访问层已经可供开发人员处理此级别的数据?

编辑:对于一些澄清, Vinko Vrsalovic说:

“我相信snicker是想谈论NO-SQL,其中事务数据是非规范化的,并在Hadoop或BigTable或Cassandrascheme中使用。

这就是我所说的。

奖励积分为那些谁赶上xkcd参考。

从我看来,关系数据库是一个通用的工具来对冲你的赌注。 现代计算机速度不够快,而且RDBMS'的优化程度已经足够,你可以在一个盒子上成长得相当可观。 通过select一个RDBMS,您可以非常灵活地访问您的数据,并且具有强大的正确性约束,使得对数据进行编码变得更容易。 然而,RDBMS不能代表任何特定问题的良好优化,它只是给你很容易改变问题的灵活性。

如果你开始快速发展,并意识到你将不得不扩展到单个数据库服务器的规模,那么你突然就有了更难做的select。 您将需要开始识别瓶颈并将其删除。 关系型数据库将成为一个令人讨厌的依赖关系,你将不得不把它分开。 数据越相互关联,你就必须做更多的工作,但是也许你不需要完全分开整个事情。 如果你读的很重,也许你可以通过简单的复制来获得。 如果你正在饱和你的市场,并且增长趋于平稳,那么也许你可以将固定数量的数据库服务器进行部分规范化和分解。 也许你只是有一些问题表,可以移动到一个更具扩展性的数据存储。 也许你的使用configuration文件是非常caching友好的,你可以将负载迁移到一个巨大的memcached群集。

在BigTable这样的可扩展键值存储中,当上述任何一个都不能工作时,如果单个types的数据太多,即使非规范化,单个表对于一个服务器来说也是太多了。 在这一点上,你需要能够任意分割,仍然有一个干净的API来访问它。 很自然地,当数据分布在如此多的机器上时,你不可能有需要这些机器相互交stream的algorithm,而许多标准的关系algorithm会需要这些algorithm。 正如你所build议的那样,这些分布式查询algorithm有可能需要比正确索引的关系数据库中等价的JOIN更多的总处理能力,但是因为它们是并行的,所以实时性能比任何单个机器都要好(假设甚至可以存放整个索引的机器)。

现在一旦您可以水平扩展您的海量数据集(通过插入更多的服务器),可扩展性的难点就完成了。 那么我不应该这么说,因为在这个规模上进行的操作和开发要比单服务器应用程序困难得多,但关键是应用程序服务器通常只能通过无共享体系结构进行扩展,只要它们可以得到他们需要及时的数据。

要回答您关于如何常用的ORM处理无法使用JOIN的问题,简短的答案是他们不 。 ORM代表对象关系映射(Object Relational Mapping),而ORM的大部分工作只是翻译谓词逻辑的强大关系范式(简单的面向对象的数据结构)。 他们给你的大部分价值根本不可能从一个键值存储中获得。 在实践中,您可能需要构build和维护适合您特定需求的自己的数据访问层,因为在这些规模上的数据configuration文件将会发生显着变化,而且我相信存在一个通用工具出现的过多折衷并成为RDBMS的主导方式。 总之,你将永远需要在这个规模上做更多的工作。

也就是说,看看在键值存储基元之上可以构build什么types的关系或其他聚集function,一定会很有趣。 在这里我没有足够的经验来具体评论,但是有关这方面的知识还有很多,比如Oracle,在学术界还有很多尚未开发的理论知识,谷歌,亚马逊,Facebook等,但已经过滤到更广泛的发展社区的知识仍然相当有限。

然而,现在很多应用程序正在转向networking,越来越多的世界人口在线,越来越多的应用程序不可避免地要扩展,最佳实践将开始显现。 知识鸿沟将由AppEngine和EC2等云服务以及Cassandra等开源数据库来减less。 在某种意义上,这与并行和asynchronous计算并行,这也正处于起步阶段。 当然是一个程序员的迷人时刻。

你从一个错误的假设开始。

数据仓库不会像事务应用程序正常化的那样正常化数据。 没有很多连接。 有相对less的。

特别是第二次和第三次正常forms违规不是一个“问题”,因为数据仓库很less更新。 而且,当它们被更新时,通常只有一个状态标志改变,使得维度行为“当前”而不是“当前”。

由于您不必担心更新,因此不会将事件分解到2NF级别,而更新不会导致exception关系。 没有更新意味着没有exception; 不分解,不join。 你可以预先join一切。

一般来说,DW数据按照星型模式进行分解。 这将引导您将数据分解为包含度量值的数字“实际”表格 – 包含单位的数字 – 以及对维度的外键引用。

维度(或“商业实体”)最好被认为是具有属性的现实世界。 这通常包括诸如地理,时间,产品,客户等等。这些东西通常具有复杂的层次结构。 层次结构通常是任意的,由各种业务报告需求定义,而不是build模为单独的表格,而只是用于聚合的维度中的列。


解决你的一些问题。

“这个join必须在应用程序方面完成”。 有点。 数据在被加载之前是“预join”的。 维度数据通常是关于维度的相关源数据的连接。 它作为一个相对平坦的结构join和加载。

它没有更新。 插入更多的历史logging而不是更新。

“但是不是开始变得昂贵?”。 有点。 加载数据需要注意。 但是,没有太多的报告/分析联合。 数据是预join的。

由于数据是预先join的,所以ORM问题在很大程度上是没有意义的。 您的ORM根据情况映射到事实或维度。 除特殊情况外,尺寸往往很小,完全适合记忆。 当你在金融(银行或保险)或公用事业,并有大量的客户数据库时是例外。 这些客户维度很less适合内存。

JOIN是一个纯粹的关系术语,并不是所有的数据库都是关系型的。

其他数据库模型还有其他build立关系的方法。

networking数据库使用find a key - fetch the reference - find a key的无限链接find a key - fetch the reference - find a key应该使用通用编程语言编程find a key - fetch the reference - find a key

代码可以在应用程序端或服务器端运行,但不是SQL ,甚至不是基于集合的。

如果devise得当,networking数据库可以比关系数据库快得多。

例如,networking数据库可以将对另一个实体的引用存储为文件中的偏移的直接指针,或者甚至存储关于该实体的信息的磁盘上的块。

这使得遍历networking加快 – 如果你写了一个高效的代码来做到这一点。

一个关系数据库只能存储引用,如整数(或三元组或高位元组)的基本值对。

要在关系数据库中find这些值,引擎应该执行以下操作:

  • 找出包含第一个值的元组在哪里
  • find第二个值
  • 在保存第二个数字所指的数据的B-Tree查找根的地址
  • 遍历这棵树
  • find指向实际表的指针(可以存储为B-Tree本身,在这种情况下指针是我们之后的行的PRIMARY KEY的值)
  • 通过指针查找表的行或遍历表
  • 最后,得到结果。

而且你只能在一定程度上控制这个。 之后,您只需发出SQL查询并等待。

为了简化开发人员的生活而不是为了达到超级速度而不pipe是什么样的关系模型。

这与程序集和高级语言相同,关系模型是高级语言。

你可能想阅读我的博客文章

  • 什么是关系数据库?

其中我试图解释几个常用数据库模型之间的差异。

当您以这种方式对数据进行非规范化处理时,可以避免join不同项目的成本; 您接受某些数据可能会被重复,并且某些组合方式可能很难,因为使用简单的查询会带来性能上的好处。

如果你不得不在应用程序级别进行任何大量的join,这意味着你还没有足够的规范化。

理想情况下,您可以对任何您想要的数据进行一次查询。 实际上,对于应用程序的任何方面,您不应该使用两个或三个以上的查询,而且任何应用程序级别的联接都将更加简单地从单独的结果集中进行检索,以便插入到视图中。

这种事情只是真正需要的海量数据集,而且涉及到各种各样的折衷。 举一个例子:BigTable不能做聚合查询,比如给你一个计数。 它可以用来给你一个大致准确的数字 – 从某种意义上说,如果你有12,149,173条logging,其中最近一小时增加了23,721条,那么你能发现的最好的是你有“约12100000条logging”。 如果你的应用程序依赖于在任何时候知道确切的数字,那么你不应该使用BigTable,是一般的态度。

像facebook这样的应用程序只有很less的数据更改,大部分时间用户正在发布新的项目。 所以当一个项目被改变时,乘法logging需要更新的事实是一个较小的问题。

这允许数据不被标准化而不会遇到更新的常见问题。

像亚马逊这样的应用程序可以将一个用户的所有数据加载到RAM中(购物车多大?),然后更新RAM中的数据并将其作为单个数据项写出。

再一次消除了大部分数据正常化的需求。

为了便于应用程序开发,您正在进行交易扩展,所以如果您不需要扩展到更高的高度,您可能希望保持RDBMS提供的应用程序开发的简易性。

我认为,在这种情况下,你将会自己完成自己的任务,并且将不得不自己推出一切。 我没有去过那里,但是对于我们的一些项目已经考虑过了。 你可以用关系数据库来获取相当大的数据(就像SO演示的那样),所以现在我将继续享受关系数据库的好处。

一般来说,数据仓库是围绕使用连接和数据拆分成维度和事实表(通过所谓的“星型模式”等)

连接通常会被预先计算并存储为非规格化表格。

我不知道任何ORM工具可以与不允许连接的数据库系统一起工作,因为这些工具通常不被视为传统的关系数据库。