【SQL开源代码栏目提醒】:网学会员在SQL开源代码频道为大家收集整理了“为 MapReduce 框架使用 SQL 类语言 - 编程语言“提供大家参考,希望对大家有所帮助!
为 MapReduce 框架使用
SQL 类语言 简介 在过去二十年中计算能力的稳步增强催生了铺天盖地的数据量这反过来引起计算架构和大型数据处理机制的范式转换。
例如天文学中的强大望远镜、物理学中的粒子加速器、生物学中的基因组测序系统都将海量数据交到了科学家手中。
Facebook 每天会收集 15TB 的数据到 PB 级的数据仓库中。
在业界例如Web 数据分析、点击流分析和网络监控日志分析和科学界例如大规模模拟产生的数据的分析、传感器部署以及高吞吐量实验室设备对大型数据挖掘和数据分析应用的需求都在增加。
尽管并行数据库系统适用于这些数据分析应用中的其中一些但是它们太过昂贵难以管理并缺乏对长期运行查询的容错性。
MapReduce 是 Google 引入的一个框架用于编程商品计算机集群以便在单个传递中执行大型数据处理。
该框架被设计为一个 MapReduce 集群可以通过容错的方式扩展到上千个节点。
但是 MapReduce 编程模型有其自身的限制。
它的单输入、两阶段数据流过于严格而且层次过低。
例如即使最常见的运算您都得编写自定义
代码。
因此许多程序员感觉 MapReduce 框架使用起来不自在而更倾向于使用
SQL 作为一种高级声明式语言。
已经开发了很多项目Apache Pig、Apache Hive 和 HadoopDB来简化程序员的任务并在 MapReduce 框架之上提供高级声明式接口。
首先了解一下 MapReduce 框架然后查看向 MapReduce 框架提供高级接口的不同系统的功能。
回页首 MapReduce 框架 MapReduce 框架方法的一个主要优势在于它将应用程序与运行分布式程序的细节分离开来比如数据分布、调度和容错问题。
在该模型中计算功能利用一组输入键/值对并产生一组输出键/值对。
MapReduce 框架的用户使用两个函数来表达计算Map 和Reduce。
Map 函数利用输入对并生成一组中间键/值对。
MapReduce 框架将与同一中间键 I shuffling 相关的所有中间值组合起来将它们传递给 Reduce 函数。
reduce 函数收到一个中间键 I 及其一组值并将它们合并起来。
通常每个 reduce 调用只产生 0 或 1 个输出值。
该模型的主要优势是支持轻松并行化和重新执行大型计算以用作主要容错机制。
Apache Hadoop 项目是一个
开源 Java?? 软件它通过实现 MapReduce 框架来支持数据密集型分布式应用程序。
它最初由 Yahoo 开发作为 Google MapReduce 基础架构的一个翻版不过随后它变得具有
开源性。
Hadoop 负责跨计算机集群运行
代码。
一般而言当一个数据集增长到超出单个物理机的存储容量时就有必要跨大量不同的计算机对其进行分区。
跨计算机集群管理存储的文件系统称为分布式文件系统。
Hadoop 随附有一个名为 HDFS Hadoop Distributed Filesystem 的分布式文件系统。
特别地HDFS 是跨 Hadoop 集群的所有节点存储文件的一个分布式文件系统。
它将文件分为大数据块并将它们分布到不同的计算机上为每个数据块制作多个副本这样一来如果有任何一台计算机发生故障数据也不会丢失。
清单 1 中的 MapReduce 程序使用伪
代码表达用于计算每个单词在文本行序列中出现的次数。
在 清单 1 中map 函数发出每个单词以及一个相关的发生标记而 reduce 函数对特定单词发出的所有标记进行汇总。
清单 1. MapReduce 程序 mapString key String value: //key: line number value: line text for each word w in value: EmitIntermediatew 1 reduceString key Iterator values: //key: a word values: a list of counts int wordCount 0 for each v in values: wordCount ParseIntv EmitAsStringwordCount 现在采用 清单 2 中文本行的输入序列。
清单 2. 输入序列 1 This is Code Example 2 Example Color is Red 3 Car Color is Green 清单 3 显示该输入的 map 函数的输出。
清单 3. map 函数的输出 This 1 is 1. Code 1 Example 1 Example 1 Color 1 is 1 Red 1 Car 1 Color 1 is 1 Green 1 清单 4 显示 reduce 函数的输出结果。
清单 4. reduce 函数的输出 Car 1 Code 1 Color 2 Example 2 Green 1 Red 1 This 1 is 3 对于程序员来说MapReduce 框架的一个主要特性是只有两个高级声明原语map 和 reduce可以使用选择的任何编程语言编写而无需担心其并行执行的细节。
另一方面MapReduce 编程模型具有其自身的局限 1. 它的单输入、两阶段数据流过于严格。
要执行具有不同数据流的任务例如联接或 n 阶段您必须得想出粗略的解决方法。
2. 即使最常见的运算例如projection 和 filter都得编写自定义
代码这导致
代码通常难以重用和维护。
3. map 和 reduce 函数的不透明性限制了系统执行优化的能力。
而且许多程序员不熟悉 MapReduce 框架倾向于使用
SQL因为他们对此更精通作为高级声明式语言来表达其任务同时将所有执行优化细节留给后台引擎。
此外不可否认的是高级语言抽象能够让底层系统更好地执行自动优化。
我们来看一下旨在应对这些问题的语言和系统并且在 MapReduce 框架之上添加
SQL 类语言。
回页首 Pig Apache Pig 项目旨在作为 Hadoop 上并行执行数据的一个引擎。
它使用一种名为 Pig Latin 的语言来表达这些数据流。
使用 Pig Latin您可以描述应当如何并行读取和处理来自一个或多个输入的数据然后将其存储到一个或多个输出中。
该语言在本着
SQL 精神使用高级声明式查询模式的表达任务和使用 MapReduce 的低级过程式编程中取得良好的折衷。
Pig Latin 数据流可以是简单的线性流也可以是复杂的工作流包括联接多个输入的流程和将数据分成将由不同运算子处理的流程。
一个 Pig Latin 程序包括一系列运算或转换它们可以应用到输入数据中以生成输出。
从整体看来运算描述了 Pig 执行环境转换成一个可执行表示然后被执行的一个数据流。
在内部Pig 将转换变成一系列 MapReduce 作业。
有了 Pig数据结构会变得更加丰富通常具有多个值且是嵌套的可以应用于数据的转换集更加强大。
尤其是Pig Latin 数据模型包含以下四个类型 1. Atom 是一个简单的原子值比如一个字符串或数字例如 “John”。
2. Tuple 是一连串字段每一个字段都可能是任何数据类型例如 quotJohnquotquotMelbournequot。
3. Bag 是具有可行副本的元组集合。
所构成元组的架构很灵活并非一个 Bag 中的所有元组都需要有同样数量和类型的字段。
图 1 中的 Bag 列出两个元组quotJohnquotquotMelbournequot 和 quotAlicequot quotUNSWquot quotSydneyquot。
图 1. 一个 Bag 4. Map 是数据项集合其中每个项目都有一个相关的键可以通过该键查询项目。
与 Bag 一样所构成数据项的架构很灵活但是键必须是图 2列表数据项的数据原子K1--gtquotJohnquotquotMelbournequot 和 K2--gt30。
图 2. 一个 Map Pig Latin 包含许多传统数据运算的算子join、sort、filter、group by、union 等并且能够让用户开发其自己的函数来读取、处理和写入数据。
MapReduce 直接提供 group by 运算实际上就是 shuffle 和 reduce 阶段而且通过实现分组的方式直接提供 order by 运算。
Filter 和 projection 可以在 map 阶段简单实现。
不过不提供其他算子尤其是 join这些算子必须由用户编写。
Pig 提供这些标准数据运算的一些复杂、非平凡的实现。
例如由于一个数据集中每个键的记录数很少均匀分布发送给 reducer 的数据常常是斜式分布的。
也就是说一个 reducer 会比其他 reducer 获得 10 倍或更多的数据。
Pig 拥有 join 和 order by 算子会处理这种情况并且在某些情况下重新平衡 reducer。
表 1 描述 Pig Latin 语言的主要算子。
在 MapReduce 中map 和 reduce 阶段内的数据处理对系统并是不透明。
这意味着 MapReduce 没有机会优化或检查用户
代码。
而 Pig 可以分析一个 Pig Latin 脚本并理解用户正描述的数据流。
MapReduce 没有一个类型系统。
这是有意的而且它允许用户灵活地使用其自己的数据类型和序列化框架。
不过缺点是这进一步限制了系统在运行时之前和期间检查用户
代码是否有错误。
所有这些要点表明编写和维护 Pig Latin 比编写和维护 MapReduce 的 Java
代码成本更低。
表 1. 表 1 Pig Latin 语言的主要算子 算子 描述 LOAD 将数据从文件系统或其他存储加载到一个关系表中 DUMP 打印关系表到系统控制台 FILTER DISTINCT 从关系表中删除重复的行 FOREACH ... GENERATE 添加或删除关系表中的字段 JOIN 联接两个或多个关系表 ORDER 根据一个或多个字段对关系表进行排序 LIMIT 将一个关系表的大小限制为最多的元组数 STORE 将一个关系表保存到文件系统或其他存储 FILTER 从关系表中删除不想要的行 GROUP 分组一个关系表中的数据 CROSS 创建两个或多个关系表的叉积 UNION 将两个或多个关系表结合为一个关系表 SPLIT 将一个关系表分成两个或多个关系表 清单 5显示一个查找所有高薪员工的简单 Pig Latin 程序。
清单 5. 查找所有高薪员工 employees LOAD employee.txt AS id name salary highSalary FILTER employees BY salary gt 100000 sortedList ORDER highSalary BY salary DESC STORE sortedList INTO highSalary _Emp DUMP sortedList 在本例中首先将输入文件加载到一个名为 employees 的 bag 中。
然后创建一个名为 highSalary 的新 bag其中仅包含 salary 字段大于 100000 的那些记录。
sortedList bag 基于 salary 值降序排列过滤的记录。
最后将 sortedList bag 的内容写到 HDFS 并打印屏幕上的 bag 内容。
清单 6显示如何使用 Pig Latin 轻松描述 join 运算。
清单 6. join 可使用 Pig Latin 轻松描述的运算 employees LOAD employee.txt AS id name salary dept departments LOAD dept.txt AS deptID deptName joinList JOIN employees BY dept departments BY deptID STORE joinList INTO joinFile 传统上即席报表是用
SQL 这样的语言完成的便于快速形成供数据回答的问题。
对于有关原生数据的研究有些用户更喜欢 Pig Latin。
由于 Pig 可在架构未知、不完整或不一致的情况下操作而且因为它可以轻松管理嵌套的数据希望在清理并将数据加载到仓库之前处理数据的研究人员通常倾向于使用 Pig。
处理大数据集的研究人员通常使用 Perl 或 Python 等脚本语言来执行其处理。
跟
SQL 的声明式查询范式比较具有这些背景的用户通常更倾向于使用 Pig 的数据流范式。
回页首 Hive Apache Hive 项目是 Facebook Data Infrastructure Team 在 Hadoop 环境之上构建的一个
开源数据仓库解决方案。
该项目的主要目标是将熟悉的关系数据库概念例如表、列、分区和
SQL 的子集引入非结构化的 Hadoop 世界同时维持 Hadoop 享有的可扩展性和灵活性。
因此它支持所有主要原语类型例如整数、浮点数、字符串以及复杂类型例如映射、列表、结构。
Hive 支持用
SQL 类声明语言 HiveQL Hive Query Language 表达的查询因此任何熟悉
SQL 的人都可以轻松理解它。
这些查询自动编译到使用 Hadoop 执行的 MapReduce 作业中。
此外HiveQL 允许用户将自定义 MapReduce 脚本插入到查询中。
HiveQL 支持 Data Definition Language DDL 语句您可以在数据库中使用该语句创建、删除和修改表。
它允许用户分别通过加载和插入 Data Manipulation Language DML 语句来加载外部来源的数据和将查询结果插入 Hive 表。
但是HiveQL 目前不支持更新和删除现有表中的行特别是INSERT INTO、UPDATE 和 DELETE 语句这支持使用非常简单的机制来处理并行读写操作而无需实施复杂的锁协议。
元存储组件是 Hive 的系统目录存储有关底层表的元数据。
该元数据在表创建期间指定且在每次 HiveQL 中引用表时被重用。
与构建于 Pig Latin 这样的 MapReduce 类架构之上的类似数据处理系统相比元存储将 Hive 区分为一种传统的仓储解决方案。
清单 7展示了 HiveQL 语句示例描述了创建表、加载数据和查询表内容的操作。
清单 7. 描述创建表、加载数据和查询表内容的操作的 HiveQL 语句 CREATE TABLE employee empID INT name STRING salary BIGINT ROW FORMAT DELIMITED FIELDS TERMINATED BY t STORED AS TEXTFILE LOAD DATA INPATH quotemployee_dataquot INTO TABLE employee SELECT FROM employee WHERE salary gt 100000 SORT BY salary DESC Hive 还通过用户创建的函数支持数据操作参见清单 8。
清单 8. Hive 通过用户创建的函数支持数据操作 INSERT OVERWRITE TABLE employee SELECT TRANSFORM empID name salary address department USING python employee_mapper.py AS empID name salary city FROM employee_data 一般而言Hive 对于来自关系数据库世界的任何人来说都是一个不错的接口不过底层实现的细节没有完全隐藏。
您仍然需要担心一些差别比如指定联接以实现最高性能的最佳方式一些缺少的语言功能。
Hive 确实支持为不适合
SQL 的情况插入自定义
代码并且提供大量工具来处理输入和输出。
Hive 存在一些局限比如它缺少对 UPDATE 或 DELETE 语句的支持且不能对单个行、日期或时间类型执行 INSERT 操作因为它们被看作是字符串。
回页首 HadoopDB 被 Hadapt 公司商业化的 HadoopDB 项目是一个混合系统旨在结合 MapReduce 的可扩展性优势和并行数据库的性能和效率优势。
HadoopDB 背后的基本思想是连接多个单节点数据库系统 PostgreSQL使用 Hadoop 作为任务协调者和网络通信层。
查询用
SQL 表达但是其执行是使用 MapReduce 框架跨节点并行化的以便将单一查询工作尽可能推送到相应的节点数据库中。
总之并行数据库系统已经出现在商业市场上有将近 20 年了现在市场上有许多不同的实现例如Teradata、Aster Data 和 Greenplum。
这些系统的主要目标是通过各种操作比如加载数据、创建索引、评估查询来改进性能。
一般而言使 MapReduce 在某些场景下较并行 RDBM 更胜一筹的一些主要原因是 及时地将大量数据格式化并加载到并行 RDBM 中是一项极具挑战且耗时的任务。
输入数据记录不总是遵循同样的架构。
开发人员通常想要灵活地添加和删除属性且对输入数据记录的解译也会随着时间而变化。
大规模数据处理会很耗时因此即使在发生故障时仍然保持分析作业运行很重要。
虽然大多数并行 RDBM 有容错支持但是集群中即使只有一个节点发生故障通常都要从头重新启动一个查询。
相比之下MapReduce 更优雅地处理故障可以仅重做由于故障丢失的那部分计算。
MapReduce 框架与并行数据库系统的比较是一项长久以来未能平息的争论。
在性能和开发复杂度方面对 MapReduce 框架的 Hadoop 实现与并行
SQL 数据库管理系统进行了大规模比较。
该比较的结果表明并行数据库系统在执行各种数据密集型分析任务时较 MapReduce 具有显著性能优势。
另一方面与并行数据库系统相比Hadoop 实现更易于设置和使用。
另外在最大限度减少硬件故障发生时丢失的工作量时MapReduce 表现出卓越的性能。
此外与非常昂贵的并行 DBMS 解决方案相比MapReduce及其
开源实现是一种非常廉价的解决方案。
最初MapReduce 框架的主要应用侧重于分析非常大型的非结构化数据集比如 Web 索引编制、文本分析和图形数据挖掘。
最近随着 MapReduce 稳步发展为事实数据分析标准它被重复用来查询结构化数据。
长期以来关系数据库一直支配着数据仓库系统的部署和对结构化数据的分析作业执行。
人们越来越对结合 MapReduce 和传统数据库系统来维护两者的优势感兴趣。
特别是HadoopDB 尝试通过继承 Hadoop 的调度和作业跟踪来实现容错和在异构环境中进行操作的能力。
它尝试通过在数据库引擎内执行大部分查询处理来实现并行数据库的性能优势。
图 3展示了 HadoopDB 的架构其中包括两层1 一个数据存储层或 HDFS2 一个数据处理层或 MapReduce 框架。
图 3. HadoopDB 的架构 在该架构中HDFS 是由中央 Name Node 管理的一个块结构文件系统。
单个文件分为固定大小的数据块且分布到集群中的多个 Data Node 中。
Name Node 维护有关数据块大小和位置以及元数据的副本。
MapReduce 框架遵循一个简单的主-从架构。
主节点是一个 Job Tracker从节点或工作节点是 Task Tracker。
Job Tracker 处理 MapReduce 作业的运行时调度并维护每个 Task Tracker 的负载和可用资源相关信息。
Database Connector 是位于集群内节点上的独立数据库系统与 Task Trackers 之间的接口。
Connector 连接到数据库执行
SQL 查询并将结果作为键-值对返回。
Catalog 组件维护有关数据库、其位置、副本位置和数据分区属性的元数据。
在加载并将单一节点分成多个较小的分区或块之后Data Loader 组件负责在给定的分区键上全局重新分配数据。
SMS Planner 扩展 HiveQL 转换器并将
SQL 转化为 MapReduce 作业该作业连接 HDFS 中作为文件存储的表。
回页首 Jaql Jaql 是专为 JavaScript Object Notation JSON 设计的一种查询语言JSON 是因其简单性和建模灵活性而很受欢迎的一种数据格式。
JSON 是表示数据从平面数据到半结构化 XML 数据的一种简单而灵活的方式。
Jaql 主要用于分析大型半结构化数据。
它是一种函数式声明查询语言适当时将高级查询重写为低级查询该低级查询由使用 Apache Hadoop 项目评估的 Map-Reduce 作业组成。
核心特性包括用户可扩展性和并行性。
Jaql 包含一个脚本语言和编译器以及一个运行时组件。
它能够处理没有架构或只有部分架构的数据。
但是Jaql 还可以利用可用的刚性架构信息用于类型检查和改进性能。
清单 9 中的以下
代码段展示了一个 JSON 文档样例。
清单 9. 一个 JSON 文档样例 id: 10 name: quotJoe Smithquot email: quotJSmithemail.comquot zip: 85150 id: 20 name: quotAlice Jonesquot email: quotAJonesemail.comquot zip: 82116 Jaql 使用一种非常简单的数据模型JDM Jaql Data Model 值可以是原子、数组或记录。
大多数原子类型受支持包括字符串、数字、零和日期。
数组和记录是可任意嵌套的复合类型。
更详细地讲一个数组是一个有序的值集合可用于建模数据结构比如矢量、列表、集合或包 bag。
一条记录是一个无序的名称-值对集合可建模结构、字典和映射。
JDM 虽然简单但很灵活。
它允许 Jaql 操作各种用于输入和输出的数据表示法包括带分隔符的文本文件、JSON 文件、二进制文件、Hardtop 的序列文件、关系数据库、键值存储或 XML 文档。
函数在 Jaql 中是一等值。
可以将它们分配给一个变量而且它们是高阶的因为可以将其作为参数传递或用作返回值。
函数是主要的可重用因素因为任何 Jaql 表达式都可封装在一个函数中且可以通过强有力的方式参数化一个函数。
清单 10 是一个包含一串函数的 Jaql 脚本示例。
清单 10. 包含一串函数的 Jaql 脚本 import myrecord countFields fnrecords records -gt transform myrecord::names -gt expand -gt group by fName as occurrences into name: fName num: countoccurrences readhdfsquotdocs.datquot -gt countFields -gt writehdfsquotfields.datquot 在本例中 read 算子从 Hadoop Distributed File System HDFS 加载原始数据并将其转换为 Jaql 值。
这些值由 countFields 子流程处理提取字段名并计算其频率。
最后 write 算子将结果存储回 HDFS。
表 2描述 Jaql 脚本语言的核心表达式。
表 2. Jaql 脚本语言的核心表达式 表达式 描述 transform transform 表达式在一个数组的每个元素上应用一个函数或投影以生成一个新数组。
expand expand 表达式常用于解除其输入数组的嵌套。
group by 类似于
SQL 中的 GROUP BYJaql 中的 group by 表达式在一个分组表达式上分割其输入并向每个组应用一个聚合表达式。
Filter filter 表达式保留特定谓词为真的输入值。
Join join 表达式支持两个或更多输入的同等联接。
用于内部和外部联接的所有选项也受支持。
Union union 表达式是一个将多个输入数组合并为一个输出数组的 Jaql 函数。
Control-flo.