基于MapReduce的连接查询算法
2015-09-20 18:03
267 查看
1 引言
1.1 研究背景
因为计算机科学的快速发展和飞速前进,计算机已经渗透到人们的生活和企业的生产当中。计算机带来的革命随处可见,因为有了物联网的存在,人们只需要在手机上触摸一下屏幕就可以买到自己想要购买的商品,因为有了微信、微博等社交网络的兴起,人与人之间的距离变得越来越小,人与人之间的交流越来越容易。但是,当计算机技术给我们带来了前所未有的用户体验和便捷的同时,这些网络传输所产生的信息量的增长也给计算机专业人员带来了前所未有的挑战。在文献[1]中可以了解到百度所产生的总数据量已经超过了1EB,每天需要处理的网页数据达到10PB~100PB;淘宝累计交易数据量高达100PB;Twitter每天发布超过两亿条信息,新浪微博每天发帖量达到8000万多条;中国移动一个省的电话通联记录数据每月可达0.5PB~1PB;一个省会城市公安局道路车辆监控数据三年可达200亿条、总量120TB。据世界权威IT信息咨询分析公司IDC研究报告预测:全世界数据量未来10年将从2009年的0.8ZB增长到2020年的35ZB(1ZB=1000EB=1000000PB),10年将增长44倍,年均增长40%。动辄达到数百TB规模的数据量早已超出了传统的关系型数据库的存储与分析能力。单机的统计和可视化的工具也因此变得无法使用,它们的缺点主要表现在以下方面:灵活性差、扩展性差、性能差等等。在此背景下,出现了一些摒弃了传统DBMS设计思想的新存储系统---NoSQL,即“Not only SQL",也就是对关系型DBMS的补充。相比较于关系型数据库来讲,NoSQL具有大得多的吞吐量、拥有更强大的水平和垂直扩展能力,更重要的是,它使用的是低端硬件集群,这样就更好地避免了昂贵的OR-Mapping。Redis、MongoDB和HBase等就是在NoSQL思想下开发出的很受市场欢迎的数据库系统。
大数据之所以这么吸引众人的眼球,并不仅仅在于它的海量数据存储,更在于它能够从海量数据中得到有价值的信息。这说的就是大数据的第二个重要意义:对海量的数据信息进行信息处理和挖掘。其重要价值已被越来越多的公司所发现并加以利用。例如,很多社交网站,就是通过数据挖掘来找到潜在的用户需求,从而能够对用户的个人喜好进行分析处理,设计出新颖的网络应用模块,比如好友之间的广告推荐等应用模块;Google更是通过对海量数据进行page-rank信息的计算,对网页进行高效准确的排名。微软公司提出的Windows Azure
Platform,用户可以通过客户端对云端资源访问、处理和分析。
在大数据风靡全球的同时,我国政府也加快了对大数据相关技术的攻关,工信部发布的《物联网十二五规划》里,把信息处理技术作为4项关键技术创新工程之一被提出来,其中包括了海量数据存储、数据挖掘、图像视频智能分析等大数据技术的重要组成部分。随着技术的日益成熟,市场逐步向前推进,受高科技的快速发展、互联网速度的进一步提高,海量数据的高效处理必然将对IT产业带来更大的推动作用。
1.2 研究现状
因为Web2.0技术在网络中的普遍应用,NoSQL得到了非常快速的发展。尽管在实际的应用系统中,已经存在了大量的NoSQL数据存储系统,但是,就其研究现状来说,许多挑战性问题还值得研究。例如:NoSQL并不具备类似关系型数据库所具有的强有力的理论;而且其并没有能考虑全局通用性的系列化的成果,并因此导致了其应用具有一定的局限性。近年来,大数据如浪潮般席卷全球,并深度改变人们的生活、工作和思维方式。世界上越来越多的国家开始从战略层面认识大数据,在政府治理领域融入大数据可视化思维和技术。目前,大数据可视化分析产品也伴随着大数据的爆发而日渐兴起。国外的此类产品已慢慢走向成熟,例如Hadoop、IBM大数据平台和Splunk等。
其中,MapReduce作为一种海量数据处理的并行编程模型,自提出以来,受到了工业界和学术界的广泛关注。目前已经广泛应用在网页索引、数据挖掘等方面。
Hadoop作为实现了Map-Reduce模型的开源分布式并行编程框架,已经在一些领域取得了显著的成效。 Hadoop主要提供了一套名为HDFS的分布式文件系统以及支持MapReduce的计算框架。此外,还提供构建在HDFS和MapReduce之上的可扩展的数据仓库Hive,结构化数据库HBase,数据流高层语言Pig,高性能分布式协同服务ZooKeeper,以及 面向大规模分布式系统的数据收集软件Chukwa等。基于Hadoop的应用已经遍地开花,尤其是在互联网领域。Yahoo!通过集群运行Hadoop,以支持web搜索的研究;Facebook借助集群运行Hadoop,以支持其数据分析和机器学习;百度则使用Hadoop进行搜索日志的分析和网页数据的挖掘工作;淘宝的Hadoop系统用于存储并处理电子商务交易的相关数据;中国移动研究院基于Hadoop的BigCloud系统用于对数据进行分析和并对外提供服务。国内的高校和科研院所基于Hadoop在数据存储、资源管理、作业调度、
性能优化、系统高可用性和安全性方面进行研究,并将研究成果多以开源形式贡献给Hadoop社区。
Facebook使用Hive作为底层数据仓库,原始手机的全站数据都要经过Hive来进行加工和分析,然后把处理过的数据返回给前台或者关系型数据中。Hive是以Hadoop作为基础的,并把开发人员所需要的SQL接口暴露出来。所以大大降低了开发成本,程序员只需要写出SQL语句就可以自动转换为MapReduce程序。另外,MapReduce作为大数据处理的并行处理架构,还是有很多问题急需解决。例如:数据查询中,连接操作不能很高效的转换为MapReduce程序。
从上面的论述来看,大数据的时代,谁能占领这块新领地,谁就能够在这一场技术之争中获胜,并成为未来计算机领域的新龙头。
1.3 研究内容
本文的主要研究基于MapReduce框架的数据查询,主要的研究内容如下几个方面:第一,如何基于大规模数据建立NoSQL的数据模型,大规模的原始数据的存储方式以及存储结构的建立与传统的SQL数据模型的不同及优点在什么地方。
第二,大规模数据存储之后,如何实现大规模的数据查询是本文研究的第二个重要内容。在此基础之上,介绍MapReduce是如何实现大规模数据查询的高效性,并了解Hive的SQL语言的易用性。
第三,对于查询扩展算法,在各种数据文件大小不同的情况下,如何选择高效的查询算法;以及在数据倾斜的状况下,如何规避reduce阶段的时间浪费。
第四,在实验环境中,就以上提出的各种算法,写出相应的实现代码,并记录各种算法的查询时间,以验证算法决策树的正确性。
1.4 论文结构
本文章节安排如下:第一章 引言。介绍了大数据时代的背景,基于NoSQL的大数据研究现状,以及数据挖掘的并行处理框架MapReduce的介绍,最后介绍了论文的组织结构和内容安排。
第二章 Hadoop平台。介绍论文涉及的主要技术,主要介绍Hadoop平台的架构和工作原理。
第三章 查询算法思想。讲解连接的种类,查询的算法设计原则和针对各种查询算法而提出的算法决策树。
第四章 数据均匀情况下的查询算法。本章详细讲述在数据均匀情况下的重分区连接、复制连接和半连接的两表等值连接算法,以及多连接的算法。
第五章 数据倾斜情况下的查询算法。本章详细讲述了在数据倾斜的情况下的连接算法。
第六章 总结与展望。总结全文内容并展望未来。
2 Hadoop平台
2.1 Hadoop平台概述
Hadoop是一个开源的分布式计算平台。文献[2]详细讲述了Hadoop平台的架构和原理。Hadoop为用户提供了系统底层的细节透明的分布式基础架构。它的设计并不是依靠硬件技术来提高可用性,而是扩展大量的廉价机器来提供本地存储和计算,又依赖能够自动检测错误的软件库来提高正确率。Hadoop是基于Google MapReduce算法写的Java实现,有很强的移植性。它能够让Hadoop程序员不用考虑细节,直接根据其提供的接口来编写上层数据挖掘代码。Hadoop是目前最流行的分布式开发框架。不仅有很好的扩容能力,并且能够自动检测失效的DataNode,并且将其失败的任务重新分配。Hadoop不仅能够保持非常快的处理速度,而且所花费的硬件资源都是廉价机器。这给了大数据处理“亲民”的形象。
作为流行的趋势,Hadoop的快速发展是有目共睹的。它的相关子项目也受到开发者的喜爱和青睐。如图2-1所示,Hadoop架构已越发完善,其相关子模块已经很多,如:可扩展的分布式数据库HBase、数据仓库Hive、计算引擎Spark、以及Zookeeper、Mahout等。
图2-1 Hadoop架构
2.2 HDFS
2.2.1 HDFS概述
HDFS是Hadoop的分布式文件系统,基于流数据访问和处理超大文件而设计开发的,能够运行在通用硬件之上。大体来讲,HDFS有以下几个优点:(1)HDFS的错误检测和快速恢复使其独领风骚。因为,在实际生产环境中,硬件错误是常态,而不是说发生了异常情况,特别是当成千上百个服务器工作时,一个组件的失灵是不可避免的。
(2)HDFS上部署的应用程序主要是以流式读为主,大多是做批量处理;所以HDFS具有数据访问的高吞吐量来支持应用程序的执行。
(3)HDFS的存储能力已经达到了PB级的数据,并且有很强的集群扩展能力。
(4)由于HDFS自身所具有的容错率,使其只需运行在廉价的商用机器集群之上就可以。
2.2.2 HDFS架构
如图2-2所示,HDFS是依赖主从结构来管理文件系统的。它包含一个NameNode和多个DataNode。很显然,主节点是NameNode,管理整个文件系统的命名空间。集群中的DataNode负责管理所在节点的存储和处理文件系统客户端的Read/Write请求。在NameNode的调度下进行数据块的操作。可以查看文献[3]连接HDFS的shell命令。图2-2HDFS工作原理
2.3 MapReduce
2.3.1 MapReduce架构
MapReduce的编程模型使用非常简易。开发出来的程序不仅具有可靠容错的能力来处理数据集,而且能够运行在上千个PC机构成的机架上。它非常简单并且易于实现、扩展性强。所以已经被广泛地应用于各种场景之中,比如日志的分析、海量数据的排序、数据之间的连接查询。Hadoop从2.0版本开始之后,MapReduce框架开始使用Yarn架构。如图2-3所示,Yarn主要有两个功能模块,一个是资源管理,另一个是任务调度、监控。ResourceManager管理所有应用程序资源的分配,每一个应用的ApplicationMaster进行相对应的协调和调度。ResourceManager和NodeManager负责管理所在机器上的进程。
图2-3 YARN工作原理
2.3.2 MapReduce计算模型
在Hadoop中,MapReduce任务会被视为一个Job。Job分为map阶段和reduce阶段,对应map函数和reduce函数。如图4所示,map函数接受形如<key,value>的输入,中间输出形如<key,value>的键值对。shuffle阶段,Hadoop会自动将所有具有相同中间key值的键值对集合到一起,然后传递给reduce函数。所以reduce函数的输入形式为<key,(listof values)>。经过reduce函数的处理后产生形如<key,value>的输出。图2-4MapReduce计算模型
2.4 Hive
Hive是Hadoop生态系统中必不可少的工具,提供了一种SQL语言,可以查询存储在HDFS中的数据。数据仓库的应用程序大多是以关系型数据库来实现的,因此它们的查询语言多是使用SQL。所以从这一层面上来说,Hive降低了将这些应用程序进行Hadoop上的转移难度,对于开发人员来讲,更是一则福音,因为他们只需掌握SQL开发就可以驾驭Hadoop。Hive提供了一个SQL解析过程,并能够从外部的接口中得到命令并解析。其中的解析过程是将SQL命令解析为MapReduce任务交给集群处理。
Hive的数据存储建立在HDFS之上。Hive本身并没有专门的数据存储格式,也不能建立索引,所以,Hive中的表是可以非常自由地组织的,只要确定了列分隔符和行分隔符就可以解析数据了。Hive的体系结构如图2-5所示。
图2-5 Hive体系
Hive中包含四种数据模型:表、外部表、分区和桶。其中,最基本的数据模型Table在hive中都有一个对应的存储目录,所有的表数据都存储在这个目录之下。其他的数据模型和HQL语言规范,你可以查看文献[4]。
3 查询算法思想
3.1 算法综述
查询算法是数据分析和挖掘中尤为重要的一步。而连接操作是查询扩展中的最常见也最重要的一项操作。所以,要想设计出优秀的算法,必须能够对连接操作有很深的理解。为了了解和明白连接算法,首先,先让我们看一下连接的种类都有哪些。依据连接条件的不同,连接一般可以分为等值连接和非等值连接;依据连接方式的不同,连接一般可以分为内连接和外连接,内连接指查询结果只包含满足连接条件的记录,外连接指的是查询结果必须包含两个数据集中的至少一个数据集中的全部记录。依照连接的数据集个数的不同一般可以分为两表连接和多表连接。
另外,还需要了解的一个状况是数据分布。主要包含两个状况,一个是数据均匀,另一个是数据倾斜。这两种状况的判断标准有两个:连接操作的连接属性的各个不同取值所映射的记录的数目的均匀程度、每个Reduce操作的数据量的均匀程度。顾名思义,如果均匀程度太小,那么这一状况称之为数据倾斜,反之为数据均匀。可以查看文献[5]了解P2P系统的查询算法。
3.2 算法决策树
每个连接策略都有自己的优点和缺点,那么,如何选择最适合和最高效的连接策略显得尤为重要,在此给出了一个决策树(注:在此不考虑多表连接的数据倾斜情况)。图3-1中的决策树可以归纳为以下四点:
(1)如果连接的数据集有两个以上(不包括两个),那么就采用多表连接。
(2)如果在数据倾斜情况之下,那么就采用数据倾斜的连接算法。
(3)在数据均匀情况之下,如果每个数据集都大到无法被缓存,那么采用重分区连接算法,即Repartition join(Reduce side join);如果数据集中有一个小到可以放进map的内存中,那么就采用复制连接算法,即Replicated join(Mapside join);如果数据集中有一个经过过滤之后可以放进map的内存之中,那么就采用半连接算法,即Semi-join。
3.3 算法设计原则
连接算法的设计原则是降低任务执行所需要的时间,使得MapReduce任务能够更加高效地完成工作。当然,效率的优化肯定是基于此过程所产生的时间代价而提出的。所以算法的设计在此基础上从三个出发点提出了设计思路。首先,减少shuffle阶段所产生的网络传输量。降低网络传输量,往往可以通过数据的过滤来实现。然后,保持reduce节点的负载均衡,因为如果reduce节点数据倾斜的话,会导致因等待某几个节点的完成任务而拖延整个MapReduce任务的时间。此效果通常是通过自定义partition函数来实现的。最后针对多连接的情况,提出了减少MapReduce轮数的方法,因为多轮的MapReduce任务造成大量的磁盘IO的操作耗时太长。比如文献[6]中的作者提出了一次任务实现多连接的情况。
数据均匀情况下的连接算法
4.1 重分区连接
4.1.1 重分区连接算法思想
重分区连接是在MapReduce编程模型中的最简单普通的实现方式,它将连接的键值作为Map的输出Key,这样在shuffle阶段,Hadoop会直接内部实现把相同Key的键值对分发给同一个reduce端。最后,Reduce端会把接收到的键值对依照标志位的不同来缓存到两个队列中,通过遍历这两个队列完成连接并输出。如图4-1,可在文献[7]中来查看Hadoop实现该算法的源码。图4-1重分区连接算法
重分区连接如果直接把map阶段的输入按照键值对的形式全部输出,那么,由map阶段传输到reduce阶段产生的网络传输量是很高的成本。因此,需要在map阶段做一些数据过滤、数据去重和数据投影以降低数据传输量。数据过滤是指在map阶段将不合规格或者不需要的冗余数据去除出去。数据去重是指在map阶段将重复数据删除出去。数据投影是指根据需要map输出的数据只保留所需要的字段,而不是全部字段输出。注:此处的数据过滤不涉及参照另一个表的情况,只是格式上的甄别,与半连接算法区分。
重分区连接还有一个问题需要考虑。在reduce端做笛卡尔积运算的时候,当数据量太大的时候,两个链表容易内存溢出。下面对此情况提出重分区算法的改进。如图4-2
图4-2 改进的重分区连接算法
改进算法的核心是对map阶段输出的key值进行扩展,不再只是指连接属性,而是将标志位和连接属性共同组成。这样的好处就是分散数据,相同join key的数据集就可以因为标志位的不同分别去到两个reduce端,减少了reduce端的压力。更有效率的是,reduce端只需缓存较小的表就可以,另一个表可以交给Hadoop内部自己管理,然后做笛卡尔积运算并输出结果。
4.1.2 重分区连接算法实现
在实现时,有两种选择:第一,使用Hive数据仓库,直接通过HQL语言来做连接。第二,MapReduce编程模型上开发源代码之后,运行在Hadoop之上来完成。下面就一一解释这两种方法的实现方式。Hive:HQL支持通常的HQL语句,它的内连接语句格式为:SELECT a.key, a.value FROMa JOIN b ON a.key = b.key(其中a,b为两个数据集,key为连接属性)。假如需要实现的是左半连接,其语句格式为:SELECT a.key,a.value FROM a LEFT OUTER JOIN b ON a.key = b.key,相应的,右半连接为:SELECT a.key, a.value FROM a RIGHT OUTER JOIN b ON a.key
= b.key。全连接为:SELECT a.key, a.value FROM a FULL OUTER JOIN b ON a.key = b.key。很明显,这种语句格式与传统的数据库连接操作语句相同,所以这给不懂Java编写Mapreduce程序的开发人员提供了便利。
MapReduce方法需要自己实现map和reduce函数。其伪代码如下:
Algorithm Name: Repartition join Input: Data files{D1,D2} Output: <Key1, Value1>, <Key2, Value2>,… , <Keyn, Valuen> 1)Map: 2) Read data from files 3) For line n in data 4) Get Value from line n text 5) If Value from D1 6) set Flag = 1 Joinkey=Value.a 7) Else 8) set Flag = 2 Joinkey=Value.b 9) Output <Joinkey, Flag+Value> to Reducer 10)End Map 11)Reduce: 12) For each <Key, List<Value>> form map 13) Get Flag from Value 14) If Flag = 1 15) Add Value to LeftList 16) If Flag = 2 17) Add Value to RightList 18) For each Value1 in LeftList 19) For each Value2 in RightList 20) Output <Value1+Value2> 21)End Reduce |
4.2 复制连接
4.2.1 广播算法
复制连接操作适用广播算法,此算法的核心是大表和小表做连接,小表小到可以放进缓存即可,这时,只需要将小的数据集广播到所有的map端,map端就可以直接做连接操作输出结果了,省去了reduce阶段和shuffle阶段所产生的网络传输和处理开销。如图所示,复制连接算法的核心原理如下:
图4-3 复制连接算法
首先,将数据集小的文件放进分布式缓存广播到所有map节点,然后map函数会将分布式缓存中的文件取出放进hashtable,最后,依据大数据集中的每条记录的join key是否存在hashtable中,并将符合的记录与hashtable连接并输出结果。
4.2.2 广播算法实现
如4.1.2讲解,本算法的实现同样有两种实现方式。其一,在Hive-0.7版本之前,该算法的实现需要在查询语句中增加/*+ MAPJOIN(b)*/标志来触发。如下所示:SELECT /*+ MAPJOIN(b) */ a.key, a.valueFROM a JOIN b ON a.key = b.key(其中a,b为两个数据集,key为连接属性)。/*+ MAPJOIN(b) */的意义是指将数据集b存放在分布式缓存中,做map操作。在Hive-0.7版本之后,放弃了这种使用方式,而是通过用户自己进行设置,其具体语句为sethive.auto.convert.join=true。在此,用户可以自己设置能够使用这个优化的小的数据集的大小。默认值为25000000B字节。其二,MapReduce的算法实现的伪代码如下:
Algorithm Name: Replicated join Input: Data files{D1,D2} Output: <Key1, Value1>, <Key2, Value2>,… , <Keyn, Valuen> 1)Add D1 to CacheFile 2)Map: 3) Read data from CacheFile 4) For line n in data 5) Get key from line n text 6) Get Value from line n text 7) Put (Key,Value) to HashMap 8) Read data from File 9) For line n in data 10) Get Value from line n text 11) Get Joinkey from Value 12) If Joinkey in HashMap 13) Get Value1 From HashMap 14) Output <Value+Value1> 15) End Map |
4.3 半连接
4.3.1 半连接算法思想
在一定的情况下,复制连接的性能是比重分区连接好很多的,但这种算法是很受局限的。虽然是大的数据集和小的数据集做连接,但并不是所有情况下小的数据集都可以缓存到内存之中。这时,如果小数据集中的很多连接属性在大数据集中并不存在,这时就可以使用半连接。先将大数据中的join key提取出来,与小数据集连接得到足够小到放进内存中的数据集。然后再做复制连接操作。可以查看文献[8]来了解此内容。下图4-4说明了半连接操作的过程。一共分为三个阶段:
图4-4 半连接算法
第一阶段的算法是map阶段将大数据集的join key放到hashtable中缓存以去重,然后在reduce端将其输出。
第二阶段的算法思想是广播算法,将第一阶段得到的数据广播给所有的map节点,然后与小的数据集在map阶段连接并输出。
第三阶段的算法思想同第二阶段相同,将第二阶段产生的文件放进分布式缓存中,广播到所有map节点,然后与大数据集做连接并输出结果。
4.3.2 半连接算法实现
半连接算法的HQL语句的实现为:Hive sql:SELECT a.key, a.value FROM a left semi JOIN b ON a.key =b.key(其中a,b为两个数据集,key为连接属性)。其中,在HQL规范中,数据集b只能通过on语句做连接条件使用,而不能出现在SELECT子句中。其MapReduce实现的伪代码如下:Algorithm Name: Semi-join First Mapreduce: Input: Data file{D1} Output: Data file{W1} 1)Map: 2) Read data from files 3) For line n in data 4) Get Value from line n text 5) Get Joinkey from Value 6) Output <Joinkey, Null> to Reducer 7)End Map 8)Reduce: 9) For each <Key, List<Value>> form map 10) Add Value to List 11) For each Value in List 12) Output <Value> 13)End Reduce Second MapReduce: Input: Data files{W1,D2} Output: Data file{W2} The steps like Replicated join algorithm Third MapReduce: Input: Data files{W1,D1} Output: <Key1, Value1>, <Key2, Value2>,… , <Keyn, Valuen> The steps like Replicated join algorithm |
4.4 多表连接
4.4.1 多表连接算法思想
很多情况下,相关联的数据文件并不是两个,而是多个。这时,出现两种情况。一种是多表共键连接,即多表的join key是相同的,这时,就可以做重分区连接,增加一个标志位即可;另一种情况是多表异键相连,这时,可以使用的方法有两种---层叠连接法和复制哈希法。顾名思义,层叠连接法就是用多个MapReduce做“连接接龙”,例如,P(A,B)、Q(B,C)、Z(C,D)三个数据集做连接,首先P、Q连接会产生中间结果集X,然后,Z、X做连接即可产生结果。很明显,连接顺序在这里是很重要的,因为中间结果集会在HDFS中有存入和读取的操作,而且如果中间结果集太大的话,在第二个MapReduce中的网络传输也是很大的。所以,层叠连接法的连接顺序是先做小表连接,再与大表连接。但是当关联的数据集数目较大时,进行过多的MapReduce作业所造成的磁盘IO代价和网络传输量是很大的。
基于上述层叠连接法的考虑,文献[9]、[10]提出了复制哈希法,可以在一个MapReduce任务里就可以实现多连接。它的设计目标是将join key相同的元组划分到同一个节点,然后就可以用一个MapReduce任务来完成多连接。它的方法思想是将所有的连接属性进行hash操作,然后将reduce节点用所有的join key所产生的hash值的多维向量进行编号,然后根据hash划分数量来将数据集复制到相应的reduce节点做等值连接并输出结果。
下面举例解释这种算法。例如P(A,B)、Q(B,C)、Z(C,D)三个数据集做连接。需要将B、C进行哈希处理。那么,reduce节点的编号形式就是(b,c)。那么数据集P将会复制到编号为(hash(b),c)(c的个数是连接属性c对应的hash划分)形式的reduce节点。通过shuffle阶段之后,相同join key的(B,C)会被广播到同一节点做连接操作。
虽然这种算法使得MapReduce任务的个数降低了,但这种复制操作所产生的网络传输量也是巨大的。在文献[11]中作者提出了复制哈希法的优化,在此就不作进一步的分析了。
4.4.2 多表连接算法实现
多表连接的算法实现,根据连接属性的个数不同而不同。首先,HQL中,对多连接的连接属性相同时,实现语句为:SELECT a.val, b.val,c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1);连接属性不唯一时,HQL语句格式为:SELECT a.val, b.val, c.val FROM aJOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)。多字段连接即生成多个mapredue,注意大表放在后面做连接,以减少网络传输量。相同连接属性的多表连接与重分区连接基本相同,在此就不多赘述了。关于多连接算法的MapReduce实现,可以查看文献[12]。
5 数据倾斜情况下的连接算法
5.1 数据倾斜情况下的算法思想
实际生产环境中,数据往往是倾斜的。往往数据的分布是遵从20-80原则的。这样导致,reduce阶段时,大部分节点已完成工作,而等待那几个数据量大很多的节点,使得整体效率变得很慢。文献[10]的作者提出了一种range partition的处理方法。其设计思想是利用自定义的partition函数来实现分区,保证每个reduce节点的数据量不会相差太大,而避免数据倾斜。分区思想是将数据集平均分配给每个reduce节点。这种算法的设计是规避了Hadoop自身的哈希方法进行分区的坏处,也没有造成更多的网络传输量。
图5-1描述了数据倾斜下算法的执行过程。
图5-1 数据倾斜下的算法思想
下面的实例中讲解了这种算法与hash算法相比的优异性。
如表5-1所示,假设map输出的数据集合是{1,1,1,2,2,2,3,5,8,8},reduce节点为3个,那么,经过hash分区后,reduce节点分别收到的数据输入为{1,1,1}、{2,2,2,5,8,8}和{3}。显然数据分配不均,造成第二个reduce节点执行时间过长。
Reduce 节点 | 1 | 2 | 3 |
分配的数据 | 1,1,1 | 2,2,2,5,8,8 | 3 |
经过range partition之后,三个节点分别获得的数据集合为{1,1,1}、{2,2,2}和{3,5,8,8}。如表5-2所示,range partition与hash partition相比,更具有可能性使reduce任务负载均衡。
分区情况 | 1,1,1 | 2,2,2 | 3,5,8,8 |
分区间隔 | 1 | 3 | |
分区范围 | <2 | [2,3) | >=3 |
虽然这种分区算法有了很大的进步,但当某几个joinkey对应的数据记录非常多时,它不可能把相同joinkey的记录分配给不同的节点,所以,在reduce端仍然有可能造成内存溢出的情况。这时,分区函数的实现可以通过抽样方法统计连接属性的分布情况,记录下倾斜数据的连接属性,在分区函数中将倾斜数据分配给多个reduce节点处理。
5.2 数据倾斜情况下的算法实现
Hadoop中,每个reduce节点默认处理的数据大小为1G。hive中也针对数据倾斜做出了解决办法。它会设定一个数据倾斜的阀值,当该阀值被超过时,会将新的值发送给还没达到的reduce节点。用户可以自行设置。其具体语句为:set hive.optimize.skewjoin= true;set hive.skewjoin.key = skew_key_threshold(default = 100000)。MapReduce方法的实现伪代码如下:Algorithm Name: Skew join //抽样方式找到倾斜的数据 1)Randomly Sample data from Data file 2)Get Joinkey from data 3)If Frequency of Joinkey in D1 > Threshold 4) Add Joinkey into Map1<Joinkey,Frequency1> 5)If Frequency of Joinkey in D2 > Threshold 6) Add Joinkey into Map2<Joinkey,Frequency2> 7)Broadcast Map to each DataNode //设置分区方式为全局分区 8)TotalSortPartition specify the partition file //Map阶段 Input: Data files{D1,D2} Output: <Key1, Value1>, <Key2, Value2>,… , <Keyn, Valuen> Map: 9) Read data from files 10) For line n in data 11) Get Value from line n text 12) Get Joinkey from Value 13) If Joinkey not in Map1 or Map2 14) Output <Joinkey, Flag+Value> to Reducer 15) Else If Joinkey in Map1 not in Map2 16) Get random number r in [0,n] 17) Output <Joinkey+TotalPartition[r],Flag+Value> 18) Else If Joinkey in Map2 not in Map1 19) for each i in [0,n] 20) Output <Joinkey+TotalPartition[i],Flag+Value> 21) Else If Frequency1 > Frequency2 22) Get random number r in [0,n] 23) Output <Joinkey+TotalPartition[r],Flag+Value> 24) Else 25) for each i in [0,n] 26) Output <Joinkey+TotalPartition[i],Flag+Value> End Map //reduce阶段 Reduce: The steps like Repartition join algorithm |
6 实验与分析
6.1 实验环境
为了实现本文提出的算法,我们搭建了Hadoop平台进行实验。实验平台包含1台PC机,我们使用伪分布式环境部署Hadoop平台。硬件配置如下:处理器:AMD Athlon(tm) II X2 255 Processor 3.10GHz 内存:4.00 GB 操作系统:CentOS 6.4 系统类型:64位操作系统 硬盘:500GB |
//生成公钥/私钥对 ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa //拷贝公钥到.ssh文件夹下的authorized_keys 文件 cat ~/.ssh/id_dsa.pub>> ~/.ssh/authorized_keys //保证authorized_keys权限为600 chmod 600 authorized_keys |
图6-1SSH登录成功
Hadoop-2.6.0配置文件的默认位置为:Hadoop安装目录下的etc/hadoop目录下。需要配置的文件有:core-site.xml,hdfs-site.xml,yarn-site.xml,mapred-site.xml。配置信息如下:
core-site.xml
<property> <name>fs.default.name</name> <value>hdfs://hadoop-yarn.dragon.org:8020</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/opt/modules/hadoop-2.2.0/data/tmp</value> </property> |
<property> <name>dfs.replication</name> <value>1</value> </property> |
<property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> |
<property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> |
6.2 实验数据
实验主要包括四个部分,所实现的算法包含重分区连接、复制连接、半连接和多表连接。实验数据为模拟仿真环境的模拟数据,输入文件包含三个文件:tb_product.dat、tb_item.dat、tb_order.dat。具体文件格式如下:
tb_product.dat:
id name category_id code is_sall 0 其他 9999 9999 0 1 手机 1 901 1 2 电脑 2 902 1 3 铅笔 3 903 1 4 橡皮 4 904 1 5 电池 5 905 1 6 杯子 6 906 1 7 鼠标 7 907 1 8 书本 8 908 1 9 衣服 9 909 1 |
id user_name age phone product_id 1 小明 18 18300001111 1 2 迈克 19 13700002222 2 2 迈克 19 13700002222 2 3 李峰 32 13512345678 3 4 刘红 23 13399993333 4 5 张旭 22 18300003333 5 6 章宁 21 13399393933 6 7 宁宁 44 13813131232 7 8 赵强 25 13444342984 8 9 赵明 25 13564342984 8 9 |
id price count product_id 1 80 1 1 2 90 3 2 3 100 1 1 4 79 3 3 5 150 5 4 |
id name category_id code is_sall orderid price count 1 手机 1 901 1 1 80 1 1 手机 1 901 1 3 100 1 2 电脑 2 902 1 2 90 3 3 铅笔 3 903 1 4 79 3 4 橡皮 4 904 1 5 150 5 |
Hive实现需要先建立表结构,然后将数据批量录入表中,再执行查询语句。其中Hive的建表和存数据的HQL语句如下:
create table tb_product(id int, name string, category_id int, code int, is_sall int) row format delimited fields terminated by '\t'; create table tb_order(id int,price int, count int,product_id int) row format delimited fields terminated by '\t'; load data local inpath '/data/tb_product.dat' overwrite into table tb_product; load data local inpath '/data/tb_order.dat' overwrite into table tb_order; |
select tb_product.*,tb_order.id,tb_order.price,tb_order.count from tb_product join tb_orderon(tb_product.id=tb_order.product_id);
得到如图6-3输出,可以看出共花费65s。
图6-3 重分区连接Hive后台输出
同样的操作步骤可以实现复制连接、半连接和多连接的算法。在此就不多做赘述了。另外,因本实验环境有限,只是在一台PC机下的伪分布式环境下完成了算法的代码实现,而未在真实环境下对重分区连接、复制连接和半连接的算法效率进行相关的实验。
7 总结展望
7.1 总结
大数据的时代已经到来。未来计算机发展的机遇更多的是在大数据和云计算方向。掌握大数据的知识将成为IT人员的必备技能。大数据的应用已经遍布生产生活的方方面面。数据的价值在大数据的概念之下被重新定义。数据挖掘被越来越多的企业所重视。数据查询是数据挖掘中的最简单有力的操作。本文就数据查询扩展算法的实现展开了讨论。首先,介绍了开发平台Hadoop的基本概念和原理。自Hadoop诞生以来,发展速度远远超过人们想象。MapReduce计算模型越来越被应用到实际生产环境中。Hadoop的子项目Hive因为其简洁的操作也受到大量开发人员的喜爱。
然后,本文的重中之重就是查询算法的思想。其算法的设计思路有三个:减少shuffle阶段的网络传输量,保持reduce节点的负载均衡和减少MapReduce执行的次数。基于第一个思路,本文提出了重分区算法、复制算法和半连接算法。基于第二个思路,本文提出了数据倾斜情况下的连接算法。基于第三个思路,本文提出了多表连接情况下的一轮MapReduce算法思想。
最后,本文根据所提出的算法思想,写出了相应的Hive实现和MapReduce实现。并在伪分布式环境下,对自己给定的数据集真正在Hadoop上实验操作并成功实现了。
7.2 未来希望
(1)在真正的实验环境中,用一些真实的数据做实验。用实验证明以上算法的优越性和适用环境。并根据实验结果再对算法做出相应的优化。(2)更加深入地学习Hadoop,掌握HBase、Pig、Mahout等Hadoop子项目。并在其基础上,更加完善和丰富算法的实现方式,并清楚各种实现方式的利弊,更加熟练地操作Hadoop的运行。
(3)连接的种类能够更加丰富,不仅仅局限于等值连接查询。掌握非等值连接和带连接等查询种类下的算法思想和算法实现。
相关文章推荐
- POJ2195 Going Home 【最小费用流】+【最佳匹配图二部】
- 认清自我,创造未来!!!
- Android PopupWindow使用之地区、学校选择二级联动
- 数据库(增、删、改、查)
- 数据库(增、删、改、查)
- prepare 预编译SQL:Mysql
- 单链表反转/逆序的两种方法
- 业界编译器Clang介绍
- Ubuntu 14.04下NFS安装配置
- 原来指针可以这么来理解,妈妈再也不用担心我的编程了
- 黑马程序员——多线程
- testlink和mantis集成
- es6 标准 Promise 学习笔记
- 理解javascript闭包和C++闭包
- 【ecmall】解决无法上传店铺logo和banner照片问题(二)
- RQNOJ 题目273 马棚问题(DP)
- hdu 1302 The Snail
- HTML+CSS页面滚动效果处理
- U3D 长按加速 使用道具
- 论写代码注释的重要性