文章目录

  • 作者
  • 公司
  • 摘要
  • 1. 简介
  • 2. 背景
  • 3. 数据模型
  • 4.嵌套列式存储
    • 4.1 重复和定义级别
      • 重复级别
      • 定义级别
      • 编码
    • 4.2 将记录拆分成列
    • 4.3 记录组装
  • 5. 查询语言
  • 6. 查询执行
    • 树结构
    • 查询调度器
  • 7. 实验
    • 本地磁盘
    • MR 和 Dremel
    • 服务树拓扑
    • 每个分片的直方图
    • 记录内聚合
    • 可扩展性
    • 落后者
  • 8. 观察
  • 9. 相关工作
  • 10. 总结
  • 11. 致谢
  • 12. 参考文献
  • 附录
    • A. 列条带化算法
    • B. 记录组装算法
    • C. FSM 构造算法
    • D. SELECT-PROJECT-AGGREGATE计算算法

作者

Sergey Melnik, Andrey Gubarev, Jing Jing Long, Geoffrey Romer, Shiva Shivakumar, Matt Tolton, Theo assilakis

公司

Google, Inc.

邮箱:{fmelnik,andrey,jlong,gromer,shiva,mtolton,theovg}@google.com

摘要

Dremel 是一个可扩展的交互式即时查询系统,用于分析只读嵌套数据。通过结合多级执行树和列式数据布局,它能够在几秒钟内对万亿行的表运行聚合查询。该系统可扩展到数千个 CPU 和 PB 级数据,并在 Google 中拥有数千名用户。在本文中,我们描述了 Dremel 的架构和实现,并解释了它如何补充基于 MapReduce 的计算。我们为嵌套记录提出了一种新颖的列式存储表示,并讨论了在系统的千个节点实例上的实验。

1. 简介

大规模分析型数据处理已在包括网络公司的多个行业中广泛应用,尤其是因为低成本存储能够收集大量关键业务数据。让分析师和工程师可便捷使用这些数据变得越来越重要。交互式响应时间通常会对数据探索、监控、在线客户支持、快速原型设计、数据流水线调试和其他任务产生质的影响。

大规模执行交互式数据分析需要高度的并行性。例如,使用当今的商用磁盘在一秒钟内读取 1 TB 的压缩数据将需要数万个磁盘。同样,CPU 密集型查询可能需要在数千个核上运行才能在几秒钟内完成。在Google,大规模并行计算是使用商用机器 [5] 的共享集群完成的。集群通常托管大量分布式应用程序,其共享资源、具有广泛变化的工作负载并在具有不同硬件参数的机器上运行。分布式应用程序中的单个工作节点执行给定任务的时间可能比其他工作节点长得多,或者可能由于故障或集群管理系统的抢占而永远无法完成。因此,处理落后者和失败者对于实现快速执行和容错[10]至关重要。

网络和科学计算中使用的数据通常是非关系型的。因此,在这些领域中,灵活的数据模型是必不可少的。编程语言中使用的数据结构、分布式系统交换的消息、结构化文档等自然适用于嵌套表示。在网络规模上对这些数据进行规范化和重组通常是令人望而却步的。嵌套数据模型是 Google [21] 和其他主要网络公司大部分结构化数据处理的基础。

本文描述了一个名为 Dremel(Dremel 是一个电动工具品牌,主要依靠速度而不是扭矩。 我们仅将此名称用于内部项目。)的系统,该系统支持对商用机器共享集群上的超大型数据集进行交互式分析。与传统数据库不同,它能够对原位嵌套数据进行操作。原位是指“就地”访问数据的能力,例如,在分布式文件系统(如 GFS [14])或另一个存储层(例如,Bigtable [8])中。Dremel 可以对此类数据执行许多查询,这些查询通常需要一系列 MapReduce(MR [12])作业,但只需要一小部分执行时间。Dremel 并不打算作为 MR 的替代品,通常与其结合使用以分析 MR 流水线的输出或快速原型化更大的计算。

Dremel 自 2006 年开始投入生产环境,在 Google 内部拥有数千名用户。公司内部署了多个 Dremel 实例,节点数从数万到数千不等。 使用该系统的示例包括:

  • 对抓取的 Web 文档进行分析。
  • 跟踪 Android Market 上应用程序的安装数据。
  • Google 产品的崩溃报告。
  • 来自 Google Books 的 OCR 结果。
  • 垃圾邮件分析。
  • 调试 Google 地图上的地图图块。
  • 托管的 Bigtable 实例中的分片迁移。
  • 在 Google 的分布式构建系统上运行的测试结果。
  • 数十万个磁盘的磁盘 I/O 统计信息。
  • 对在 Google 数据中心运行的作业进行资源监控。
  • Google 代码库中的符号和依赖项。

Dremel 基于 Web 搜索和并行 DBMS 的想法建立。首先,它的架构借鉴了分布式搜索引擎 [11] 中使用的服务树的概念。就像网络搜索请求一样,查询被沿着树下推并在每一步都被重写。查询的结果是通过聚合从树的低层收到的回复来组装的。其次,Dremel 提供了一种高层的、类 SQL 的语言来表达即时查询。与 Pig [18] 和 Hive [16] 等的层次相比,它本地执行查询,而无需将它们转换为 MR 作业。

最后,也是很重要的一点,Dremel 使用列条带存储表示,这使它能够从二级存储读取更少的数据,并由于压缩成本更低而降低了 CPU 成本。列存储已被用于分析关系数据 [1],但据我们所知,尚未扩展到嵌套数据模型。Google 的许多数据处理工具都支持我们提出的列式存储格式,包括 MR、Sawzall [20] 和 FlumeJava [7]。

在本文中,我们做出了以下贡献:

  • 我们为嵌套数据定义了一种新颖的列式存储格式。我们提出了将嵌套记录分解为列并重新组装它们的算法(第 4 节)。
  • 我们概述了 Dremel 的查询语言和执行。两者都旨在对列条带嵌套数据进行有效操作,并且不需要重构嵌套记录(第 5 节)。
  • 我们展示了 Web 搜索系统中使用的执行树如何应用于数据库处理,并解释它们在有效解答聚合查询方面的优势(第 6 节)。
  • 我们展示了在 1000-4000 个节点上运行的系统实例上进行的万亿条记录、多 TB 数据集的实验(第 7 节)。

本文的结构如下。在第 2 节中,我们解释了 Dremel 如何结合其他数据管理工具用于数据分析。第 3 节介绍了它的数据模型。第 4-8 节介绍了上面列出的主要贡献。相关工作在第 9 节讨论。第 10 节是总结。

2. 背景

我们首先通过一个场景来说明交互式查询处理如何适应更广泛的数据管理生态系统。假设 Google 的工程师 Alice 想出了一个从网页中提取新型信号的新想法。她运行了一个 MR 作业,该作业通过输入数据生成一个包含新信号的数据集,存储在分布式文件系统中的数十亿条记录中。为了分析她的实验结果,她启动了 Dremel 并执行了几个交互式命令:

DEFINE TABLE t AS /path/to/data/*
SELECT TOP(signal1, 100), COUNT(*) FROM t

她的命令在几秒钟内执行完成。她运行了一些其他查询,以证明自己她的算法有效。她发现了信号 1 中的不规则性,并通过编写 FlumeJava [7] 程序进行更深入的挖掘,该程序对她的输出数据集执行更复杂的分析计算。一旦问题得到解决,她就会建立一个流水线来连续处理传入的输入数据。她制定了一些预先定制的 SQL 查询,将她的流水线的结果在各个维度上聚合起来,并将它们添加到交互式仪表盘中。最后,她将新数据集注册到目录中,以便其他工程师可以快速定位和查询。

上述场景需要查询处理器和其他数据管理工具之间的相互操作。第一个要素是通用存储层。Google 文件系统(GFS [14])就是公司广泛使用的一种分布式存储层。GFS 使用副本来保留数据,即使硬件出现故障,并在出现落后者的情况下实现快速的响应时间。高性能存储层对于原位数据管理至关重要。它允许在没有耗时的加载阶段情况下访问数据,加载阶段是分析数据处理 [13] 中数据库使用的主要障碍,在 DBMS 能够加载数据并执行单个查询之前分析数据处理通常可能需要运行很多个 MR 分析。作为一个额外的好处,可以使用标准工具方便地操作文件系统中的数据,例如,传输到另一个集群、更改访问权限或根据文件名识别数据子集进行分析。

构建可相互操作的数据管理组件的第二个要素是共享存储格式。事实证明,列式存储对于平面关系数据是成功的,但要使其在 Google 中适用,需要使其适应嵌套数据模型。图 1 说明了主要思想:嵌套字段(例如 A.B.C)的所有值都连续存储。因此,无需读取 A.EA.B.D 等即可检索 A.B.C。我们面临的挑战是如何保留所有结构信息并能够从字段的任意子集重建记录。接下来我们讨论我们的数据模型,然后转向算法和查询处理。


图 1:嵌套数据的行表示与列表示

3. 数据模型

在本节中,我们将介绍 Dremel 的数据模型并介绍一些稍后使用的术语。数据模型起源于分布式系统的上下文(这解释了它的名称,“Protocol Buffers”[21]),在 Google 被广泛使用,并作为开源实现提供。数据模型基于强类型嵌套记录。它的抽象语法由下式给出:

T = dom | < A1 : T[*|?],...,An : T[*|?]>|

其中 T 是原子类型或记录类型。dom 中的原子类型包括整数、浮点数、字符串等。记录由一个或多个字段组成。记录中的字段 i 具有名称 Ai 和可选的多重性标签。重复字段 (*) 可能在一条记录中出现多次。它们被解释为值列表,即记录中字段出现的顺序很重要。记录中的可选字段 (?)可能缺失。反之,如果一个字段是必需的,则必须正好出现一次。

为了说明这一点,请参考图 2。它描述了一个模式,该模式定义了一个记录类型 Document,表示一个 Web 文档。模式定义使用 [21] 中的具体语法。一个 Document 有一个必需的整型 DocId 和可选的 Links 字段,其中 Links 包含一个持有其他网页的 DocIds 的 Forward 和 Backward 条目的列表。一个文档可以有多个 Names,其是可以引用该文档的不同 URL。一个 Name 包含一系列 Code 和(可选的)Country 对。图 2 还显示了符合模式的两个示例记录 r1 和 r2。使用缩进来概述记录结构。我们将使用这些示例记录来解释下一节中的算法。模式中定义的字段形成树层次结构。嵌套字段的完整路径使用通常的点符号表示,例如 Name.Language.Code

嵌套数据模型支持平台中立的、可扩展的机制,用于序列化 Google 中的结构化数据。代码生成工具为 C++ 或 Java 等编程语言生成绑定。使用记录的标准二进制在线表示实现跨语言互操作性,其中字段值在记录中出现时按顺序排列。这样,用 Java 编写的 MR 程序可以使用来自通过 C++ 库生成的数据源的记录。因此,如果记录以列式表示存储,那么快速组装它们对于与 MR 和其他数据处理工具的互操作很重要。


图 2:两个示例嵌套记录及其模式

4.嵌套列式存储

如图 1 所示,我们的目标是连续存储给定字段的所有值以提高检索效率。在本节中,我们将解决以下挑战:列格式记录结构的无损表示(第 4.1 节)、快速编码(第 4.2 节)和高效的记录组装(第 4.3 节)。

4.1 重复和定义级别

值本身并不能表达记录的结构。给定重复字段的两个值,我们不知道该值在什么“级别”重复(例如,这些值是来自两个不同的记录,还是同一记录中的两个重复值)。同样,如果可选字段缺失了,我们不知道明确定义了哪些封闭记录。因此,我们引入了重复和定义级别的概念,其定义如下。作为参考,请参见图 3,其中总结了我们示例记录中所有原子字段的重复和定义级别。


图 3:图 2 中示例数据的列条带式表示,显示了重复级别 ® 和定义级别 (d)

重复级别

考虑图 2 中的 Code 字段。它在 r1 中出现了 3 次。“en-us”和“en”出现在第一个 Name 中,而“en-gb”在第三个 Name 中。为了消除这些出现的歧义,我们为每个值附加了一个重复级别。它告诉我们该值在字段路径中的哪个重复字段重复。字段路径 Name.Language.Code 包含两个重复的字段,Name 和 Language 。因此,Code 的重复级别在 0 到 2 之间;级别 0 表示新记录的开始。现在假设我们自上而下扫描记录 r1。当我们遇到’en-us’时,我们没有看到任何重复的字段,即重复级别为0。当我们看到’en’时,字段 Language 已经重复,所以重复级别为2。最后,当我们遇到’en-gb’时 , Name 是最近重复的(Language 只出现在 Name 之后一次),所以重复级别为 1,因此 r1 中 Code 值的重复级别为 0, 2, 1。

请注意,r1 中的第二个 Name 不包含任何 Code 值。为了确定“en-gb”出现在第三个 Name 中而不是第二个 Name 中,我们在“en”和“en-gb”之间添加了一个 NULL 值(参见图 3)。Code 是 Language 中的必填字段,因此缺少它的事实意味着未定义 Language。但一般来说,确定嵌套记录存在的级别需要额外的信息。

定义级别

具有路径 p 的字段的每个值,尤其是每个 NULL 都有一个定义级别,用于指定记录路径 p 中实际存在的可能未定义的字段(因为它们是可选的或重复的)的数量。为了说明这一点,请观察 r1 没有 Backward 链接。 但是,定义了 Links 字段(在级别 1)。为了保留此信息,我们将定义级别为 1 的 NULL 值添加到 Links.Backward 列。类似地,r2 中缺失的 Name.Language.Country 具有定义级别 1,而其在 r1 中的出现缺失分别具有定义级别 2(在 Name.Language 内部)和 1(在 Name 内部)。

我们使用整数定义级别而不是 is-null 比特位,以便叶子字段(例如 Name.Language.Country)的数据包含有关其父字段出现的信息;第 4.3 节给出了如何使用此信息的示例。

上面概述的编码无损地保留了记录结构。由于篇幅原因,我们省略了证明过程。

编码

每列都存储为一组块。 每个块包含重复和定义级别(以下简称为级别)和压缩后的字段值。NULL 不会显式存储,因为它们由定义级别决定:任何小于字段路径中重复和可选字段的定义级别数量都表示 NULL。不会为始终定义的值存储定义级别。同样,重复级别仅在需要时存储;例如,定义级别 0 意味着重复级别 0,因此可以省略后者。事实上,在图 3 中,没有为 DocId 存储级别。级别被打包为比特位序列。我们只根据需要使用尽可能多的位;例如,如果最大定义级别为 3,则每个定义级别使用 2 位。

4.2 将记录拆分成列

上面我们介绍了一种列式格式的记录结构编码。我们解决的下一个挑战是如何有效地生成具有重复和定义级别的列条带。

计算重复和定义级别的基本算法在附录 A 中给出。该算法递归记录结构并计算每个字段值的级别。如前所述,即使缺少字段值,也可能需要计算重复和定义级别。Google 使用的许多数据集都是稀疏的;具有数千个字段的模式并不少见,在给定的记录中只使用其中的一百个。因此,我们尝试尽可能低成本地处理缺失的字段。为了生成列条带,我们创建了一个字段写出者的树,其结构与模式中的字段层次结构相匹配。基本思想是仅在记录拥有自己的数据时才更新字段写出者,除非绝对必要,否则不要尝试沿树向下传播父状态。为此,子节点写出者从父节点那里继承了级别。每当添加新值时,子节点写出者都会同步其父节点的级别。

4.3 记录组装

高效地从列数据中组装记录对于面向行记录的数据处理工具(例如 MR)至关重要。给定一个字段子集,我们的目标是重建原始记录,就好像它们只包含所选字段一样,而所有其他字段都被剥离了。关键思想是这样的:我们创建了一个有限状态机 (FSM),它读取每个字段的字段值和级别,并将这些值按顺序添加到输出记录中。FSM 状态对应于每个选定字段的字段读取器。状态转换标记有重复级别。一旦读取器获取了一个值,我们就会查看下一个重复级别来决定下一个要使用的读取器。对于每个记录,FSM 从开始状态到结束状态遍历一次。

图 4 显示了在我们的运行示例中重建完整记录的 FSM。开始状态是DocId。读取 DocId 值后,FSM 转换为 Links.Backward。在所有重复的 Backward 值被处理完后,FSM 跳转到 Links.Forward 等。记录组装算法的详细信息在附录 B 中。


图 4:完整的记录组装自动机。边缘标有重复级别。

为了勾勒 FSM 转换是如何构建的,令 l 是当前字段 f 的读取器返回的下一个重复级别。从模式树中的 f 开始,我们找到它在第 l 级别重复的祖先,并选择该祖先中的第一个叶子字段 n。这给了我们一个 FSM 转换 (f, l) -> n 。例如,让 l = 1f = Name.Language.Country 读取的下一个重复级别。 其重复级别为 1 的祖先是 Name,其第一个叶子字段是 n = Name.Url。FSM 构造算法的详细信息在附录 C 中。

如果只需要检索字段的子集,我们构建一个更简单的 FSM,执行起来成本更低。图 5 描绘了用于读取字段 DocId 和 Name.Language.Country 的 FSM。 图中显示了自动机生成的输出记录 s1 和 s2。请注意,我们的编码和组装算法保留了字段 Country 的封闭结构。这对于需要访问如在第二个 Name 的第一个 Language 中出现的 Country 字段的应用很重要。在 XPath 中,这对应于计算表达式,如 /Name[2]/Language[1]/Country,的能力。


图 5:用于从两个字段组装记录的自动机及其生成的记录

5. 查询语言

Dremel 的查询语言基于 SQL,旨在在列式嵌套存储上高效实现。正式定义语言超出了本文的范围。相反,我们来说明它的特色。每个 SQL 语句(及其转换为的代数运算符)将一个或多个嵌套表及其模式作为输入,并生成一个嵌套表及其输出模式。图 6 描述了一个执行投影、选择和记录内聚合的示例查询。该查询是在图 2 中的表 t = {r1, r2} 上进行计算的。这些字段使用路径表达式进行引用。尽管查询中不存在记录构造函数,但查询会生成嵌套结果。


图 6:示例查询、其结果和输出模式

为了解释该查询做了什么,可以参考选择操作(WHERE 子句)。将嵌套记录视为带标签的树,其中每个标签对应一个字段名称。选择算子裁剪掉不满足指定条件的树的分支。因此,只有那些在 Name.Url 被定义并以 http 开头的嵌套记录被保留。接下来,考虑投影。SELECT 子句中的每个标量表达式都在与该表达式中使用的最重复输入字段相同的嵌套级别输出一个值。因此,字符串连接表达式在输入模式中的 Name.Language.Code 级别输出字符串值。COUNT 表达式说明了记录内聚合。聚合在每个 Name 子记录内完成,并将每个 Name 在 Name.Language.Code 中出现的次数作为非负 64 位整数 (uint64) 输出。

该语言支持嵌套子查询、记录间和记录内聚合、top-k、连接、用户自定义函数等;实验部分举例说明了其中一些功能。

6. 查询执行

为简单起见,我们在只读系统的上下文中讨论其核心思想。许多 Dremel 查询是一次性聚合;因此,我们将专注于解释这些查询并将它们用于下一节中的实验。我们将连接、索引、更新等的讨论推迟到未来的工作中。

树结构

Dremel 使用多级服务树来执行查询(参见图 7)。根服务器接收传入的查询,从表中读取元数据,并将查询路由到服务树中的下一个层级。 叶子服务器与存储层通信或访问本地磁盘上的数据。考虑下面的简单聚合查询:

SELECT A, COUNT(B) FROM T GROUP BY A

当根服务器收到上述查询时,它确定包含 T 的所有表分区,即表的水平分区,并按如下方式重写查询:

SELECT A, SUM(c) FROM (R11 UNION ALL ... R1n) GROUP BY A

表 R11,…,R1n 分别是发送到服务树层级 1 的节点 1,…, n 的查询结果:

R1i = SELECT A, COUNT(B) AS c FROM T1i GROUP BY A

T1i 是由服务器 i 在级别 1 处理的 T 中的一个无交集分区。每个服务层级执行类似的重写。最终,查询到达叶子,叶子服务器并行扫描 T 中的分片。在向上的过程中,中间服务器执行部分结果的并行聚合。上面介绍的执行模型非常适合返回中小型结果的聚合查询,这是一类非常常见的交互式查询。大型聚合和其他类别的查询可能需要依赖于并行 DBMS 和 MR 中已知的执行机制。


图 7:服务器节点内的系统架构和执行

查询调度器

Dremel 是一个多用户系统,即通常同时执行多个查询。查询调度器根据查询的优先级调度查询并平衡负载。它的另一个重要作用是在一台服务器变得比其他服务器慢得多或有一个分片副本无法访问时提供容错功能。

每个查询中处理的数据量通常大于可供执行的处理单元的数量,我们称之为槽。一个槽对应于叶子服务器上的一个执行线程。例如,一个由 3,000 个叶子服务器组成的系统,每个服务器使用 8 个线程,这样有 24,000 个插槽。因此,通过为每个插槽分配大约 5 个分片,就可以处理一个包含 100,000 个分片的表。在查询执行期间,查询调度程序计算分片处理时间的直方图。如果一个分片的处理时间过长,它会将其重新调度到另一台服务器上。某些分片可能需要多次重新调度。

叶子服务器列式读取嵌套数据的条带。每个条带中的块都是异步预读取的;预读缓存通常达到 95% 的命中率。分片通常是三副本的。当叶子服务器无法访问一个分片副本时,它会转移到另一个副本。

查询调度器遵循一个参数,该参数指定在返回结果之前必须扫描的分片的最小百分比。正如我们即将展示的那样,将此参数设置为较低的值(例如,98% 而不是 100%)通常可以显著加快执行速度,尤其是在使用较小的副本因子时。

每个服务器都有一个内部执行树,如图 7 右侧所示。内部树对应于物理查询执行计划,包括对标量表达式的计算。为大多数标量函数生成优化的、特定于类型的代码。投影-选择-聚合查询的执行计划由一组迭代器组成,这些迭代器以步伐一致的方式扫描输入列并输出聚合和标量函数的结果,这些结果标注了正确的重复和定义级别,在查询执行期间完全跳过记录组装。有关详细信息,请参见附录 D。

一些 Dremel 查询,例如 top-k 和 count-distinct,使用已知的一次性算法(例如,[4])返回近似结果。

7. 实验

在本节中,我们计算 Dremel 在 Google 中使用的多个数据集上的性能,并检验列式存储对嵌套数据的有效性。 在我们的研究中使用的数据集的属性在图 8 中进行了总结。在未压缩、无副本的形式中,数据集占据了大约 1 PB 的空间。除了一张两副本表外,其余所有表都是三副本的,并且包含 100K 到 800K 大小不等的数据分片。我们首先检验单台机器上的基本数据访问特征,然后展示列式存储如何使 MR 执行受益,最后关注 Dremel 的性能。这些实验是在正常业务运营期间在邻近许多其他应用的两个数据中心运行的系统实例上进行的。除非另有说明,否则执行时间是五次运行的平均值。下面使用的表和字段名称是匿名的。


图 8:实验研究中使用的数据集

本地磁盘

在第一个实验中,我们检验了列式存储与行式存储的性能权衡,扫描了包含大约 300K 行的表 T1 的 1GB 片段(参见图 9)。数据存储在本地磁盘上,以压缩的列式表示形式占用大约 375MB。行式格式使用更重的压缩以使在磁盘上的大小大致相同。实验是在双核 Intel 机器上完成的,该机器的磁盘提供 70MB/s 的读取带宽。所有上报的时机点都是冷启动的;在每次扫描之前刷新操作系统缓存。

该图显示了五条图线,说明了读取和解压缩数据以及组装和解析字段子集的记录所需的时间。图线 (a)-© 概括了列式存储的结果。这些图线中的每个数据点都是通过对 30 次运行的测量结果进行平均获得的,在每次运行中随机选择一组具有给定基数的列。图线 (a) 显示了读取和解压时间。图线 (b) 添加了从列组装嵌套记录所需的时间。图线 © 显示将记录解析为强类型 C++ 数据结构所需的时间。

图线 (d)-(e) 描绘了访问行存储上的数据的时间。图线 (d) 显示了读数和解压时间。大部分时间都花在解压上;事实上,压缩后的数据可以在花费大约一半的时间内从磁盘读取。如图线 (e) 所示,解析在读取和解压时间之上又增加了 50%。这些代价是为所有字段付出的,包括那些不需要的字段。


图 9:从本地磁盘读取时的性能细目(表 T1 的 300K 个记录片段)

这个实验的主要结论如下:当读取的列很少时,列式表示的增益大约是一个数量级。列嵌套数据的检索时间随字段数呈线性增长。记录组装和解析很昂贵,每个都可能使执行时间加倍。我们在其他数据集上观察到了类似的趋势。一个自然要问的问题是顶部图和底部图的交叉点,即行式存储开始优于列式存储。根据我们的经验,交叉点通常位于数十个字段,但它因数据集而异,并取决于是否需要记录组装。

MR 和 Dremel

接下来,我们将说明在列数据与行数据上的 MR 和 Dremel 执行。我们考虑访问单个字段的情况,其性能提升最明显。可以使用图 9 的结果推断多列的执行时间。在本实验中,我们计算表 T1 的字段 txtField 中的平均分词数。MR 执行是使用以下 Sawzall [20] 程序完成的:

numRecs: table sum of int;
numWords: table sum of int;
emit numRecs <- 1;
emit numWords <- CountWords(input.txtField);

记录数存储在变量 numRecs 中。对于每条记录,numWords 会累加 CountWords 函数返回的 input.txtField 中的分词数。程序运行后,平均词频可以通过公式 numWords/numRecs 计算。 在 SQL 语言中,此计算表示为:

Q1: SELECT SUM(CountWords(txtField)) / COUNT(*) FROM T1

图 10 以对数刻度显示了两个 MR 作业和 Dremel 的执行时间。两个 MR 作业都在 3000 个工作节点上运行。类似地,使用 3000 个节点的 Dremel 实例来执行查询 Q1。Dremel 和基于列式数据的 MR 读取约 0.5TB 的压缩列数据,而基于行数据的 MR 读取约 87TB。如图所示,通过从行存储转换为列存储(从几小时到几分钟),MR 的效率提高了一个数量级。另一个数量级提高是通过使用 Dremel 实现的(从几分钟到几秒)。


图 10:MR 和 Dremel 在列式存储与行式存储上的执行(3000 个节点,850 亿条记录)

服务树拓扑

在下一个实验中,我们将展示服务树深度对查询执行时间的影响。我们考虑表 T2 上的两个 GROUP BY 查询,每个查询执行都使用对数据的单次扫描。表 T2 包含 240 亿条嵌套记录。每条记录都有一个包含数字 amount 的重复字段 item 。字段 item.amount 在数据集中重复了大约 400 亿次。 第一个查询按 country 汇总 item.amount

Q2: SELECT country, SUM(item.amount) FROM T2 GROUP BY country

它返回几百条记录并从磁盘读取大约 60GB 的压缩数据。第二个查询对具有选择条件的文本字段 domain 执行 GROUP BY。它读取大约 180GB 并生成大约 110 万个不同的 domain :

Q3: SELECT domain, SUM(item.amount) FROM T2WHERE domain CONTAINS ’.net’GROUP BY domain

图 11 显示了作为服务器拓扑的一个函数的每个查询的执行时间。在每个拓扑中,叶子服务器的数量保持 2900 个不变,因此我们可以假设相同的累积扫描速度。在 2 级拓扑 (1:2900) 中,单个根服务器直接与叶子服务器通信。对于 3 级别拓扑,我们使用 1

【翻译】Dremel: Interactive Analysis of WebScale Datasets相关推荐

  1. Dremel - Interactive Analysis of WebScale Datasets

    http://highscalability.com/blog/2010/8/4/dremel-interactive-analysis-of-web-scale-datasets-data-as-a ...

  2. [翻译] Dremel made simple with Parquet

    首先自己的 blog 好久没有写技术相关的东西了,今天又动笔了,好高兴!然后转载请注明出处.最后开始正题: 原文:Dremel made simple with Parquet | Twitter E ...

  3. 【翻译】Mathematical Analysis of Algorithms

    这是Knuth 的一篇论文,原文下载在这里有:http://download.csdn.net/detail/u013012544/6982095,是北京大学本科生算法设计与分析2014年春季课程的必 ...

  4. 文献翻译Complex integrated analysis of lncRNAs-miRNAs-mRNAs in oral squamous cell carcinoma(2)

    材料和方法 获取微阵列数据和选择数据集头颈部鳞状细胞癌的基因表达数据 (HNSCC)从Cancer Genome Atlas下载(TCGA)数据库(https://gdc-portal.nci.nih ...

  5. 分布式系统领域经典论文翻译集

    分布式领域论文译序 sql&nosql年代记 SMAQ:海量数据的存储计算和查询 一.google论文系列 1.      google系列论文译序 2.      The anatomy o ...

  6. Dremel made simple with Parquet (Parquet 原理分析)

    原版地址:https://blog.twitter.com/engineering/en_us/a/2013/dremel-made-simple-with-parquet.html 写在前面: 本来 ...

  7. Google Dremel 理解

    在阅读参考2中的翻译的时候,对论文中说的如何把嵌套结构转化成在Dremel实际的存储的格式有些许疑惑,在看了参考1后才恍然大悟,于是要在这里把文献中的几个图是怎么生成的具体过程做一个详细操作 在这里, ...

  8. RDD论文翻译:基于内存的集群计算容错抽象

    该论文来自Berkeley实验室,英文标题为:Resilient Distributed Datasets: A Fault-Tolerant Abstraction for In-Memory Cl ...

  9. Google Dremel数据模型详解(下)

    "神秘"的r和d 单从数据结构来看的话,我们可以这样解释r和d的含义.r代表着当前字段与前一字段的关系,是在哪一层合并的,即公共的父结点在哪?举例来说,假如我们重建到了Code=' ...

最新文章

  1. asp.net mvc view中支持多个实体强类型小技巧
  2. 安全 - MySQL 出现严重的密码安全漏洞,许多系统存在风险
  3. marked Options
  4. Oracle行列转换的思考与总结
  5. latex 数学公式_技能分享——LaTeX篇I
  6. 使用air进行移动app开发常见功能和问题(二)
  7. SpringBoot基础教程1-1-2 配置文件介绍
  8. c语言数据结构和数据类型_C语言中的数据类型
  9. c语言面试100问题及答案,【编程C语言面试题】面试问题:C语言面试大全… - 看准网...
  10. 钉钉考勤报表生成工具
  11. pilz pnoz s4说明书_如何使用Pilz的安全继电器PNOZ S4?
  12. 企业级无线无缝漫游之思创漫游3.0 Plus ,三层漫游
  13. 学生每日计划表_小学生每日学习计划安排表
  14. linux抓取vlan数据包,Wireshark/Ethereal抓取数据包不显示vlan tag的解决方法
  15. 红帽linux性能参数,红帽企业版Linux6性能调节指引.PDF
  16. 组织行为学笔记(4)——人格与价值观
  17. (十四)单词之各动词讲解
  18. CSP-S 蒟蒻啊qaq
  19. GD32450i-EVAL学习笔记 12 - EXMCNandFlash
  20. PCIe扫盲——PCIe总线怎样做到在软件上兼容PCI总线

热门文章

  1. http协议及apache配置
  2. mysql用update方法更改用户密码
  3. F5 Networks:应用交付的“4G”挑战
  4. Amazon EBS 卷类型
  5. 视频画中画制作,一款简单好上手的软件
  6. 加州欧文计算机工程专业,加州大学欧文分校计算机工程排名第29(2020年TFE美国排名)...
  7. 认识RAM、ROM、CACHE
  8. 【TensorFlow基础操作笔记】图+对话+张量+变量+线性回归实例
  9. 咸鱼CAD笔记—编辑工具
  10. 痛心!中兴程序员跳楼始末:或成其公司内部矛盾牺牲品