描述如何提炼货车运输IOT数据。数据包括车辆,设备,乘客地图信息。目的是建立位置信息关联,分析风险。
条件:一个卡车车队,每辆车有位置信息和事件数据。这些事件数据存放于一个数据中心。
sandbox是一个简单的,预先配置的学习环境,包含最新的Apache Hadoop,HDP。包装在一个虚拟环境中,可在云端或者个人电脑使用。
Hadoop生态
Files View
,查看数据页面设置写权限
1. 点击数据;
2. 点击 Permissions
;
3. 修改权限。
Hive主要有三个功能,数据摘要,查询和分析。Hive作为一个ETL工具。
Hive从0.11版本开始提供了ORC的文件格式,ORC文件不仅仅是一种列式文件存储格式,最重要的是有着很高的压缩比,并且对于MapReduce来说是可切分(Split)的。因此,在Hive中使用ORC作为表的文件存储格式,不仅可以很大程度的节省HDFS存储资源,而且对数据的查询和处理性能有着非常大的提升,因为ORC较其他文件格式压缩比高,查询任务的输入数据量减少,使用的Task也就减少了。
使用ORC文件提升了Hive读写处理数据的性能。
CREATE TABLE ... STORED AS ORC ...
select * from trucks limit 10;
默认情况下,当在Hive中创建一个表,会在HDFS的/apps/hive/warehouse
目录下创建一个同名文件夹
业务目标是更好地了解司机疲劳,过度使用卡车,以及各种运输事件对风险的影响。为此,我们主要使用SQL对源数据进行一些转换,然后使用PIG和Spark对风险进行计算,最后使用Zeppelin进行可视化展示。
首先进行转换,我们想要得到每辆卡车每加仑汽油的里程数。首先得到每辆卡车的里程数和汽油加仑数。
CREATE TABLE truck_mileage STORED AS ORC AS SELECT truckid, driverid, rdate, miles, gas, miles / gas mpg FROM trucks LATERAL VIEW stack(54, 'jun13',jun13_miles,jun13_gas,'may13',may13_miles,may13_gas,'apr13',apr13_miles,apr13_gas,'mar13',mar13_miles,mar13_gas,'feb13',feb13_miles,feb13_gas,'jan13',jan13_miles,jan13_gas,'dec12',dec12_miles,dec12_gas,'nov12',nov12_miles,nov12_gas,'oct12',oct12_miles,oct12_gas,'sep12',sep12_miles,sep12_gas,'aug12',aug12_miles,aug12_gas,'jul12',jul12_miles,jul12_gas,'jun12',jun12_miles,jun12_gas,'may12',may12_miles,may12_gas,'apr12',apr12_miles,apr12_gas,'mar12',mar12_miles,mar12_gas,'feb12',feb12_miles,feb12_gas,'jan12',jan12_miles,jan12_gas,'dec11',dec11_miles,dec11_gas,'nov11',nov11_miles,nov11_gas,'oct11',oct11_miles,oct11_gas,'sep11',sep11_miles,sep11_gas,'aug11',aug11_miles,aug11_gas,'jul11',jul11_miles,jul11_gas,'jun11',jun11_miles,jun11_gas,'may11',may11_miles,may11_gas,'apr11',apr11_miles,apr11_gas,'mar11',mar11_miles,mar11_gas,'feb11',feb11_miles,feb11_gas,'jan11',jan11_miles,jan11_gas,'dec10',dec10_miles,dec10_gas,'nov10',nov10_miles,nov10_gas,'oct10',oct10_miles,oct10_gas,'sep10',sep10_miles,sep10_gas,'aug10',aug10_miles,aug10_gas,'jul10',jul10_miles,jul10_gas,'jun10',jun10_miles,jun10_gas,'may10',may10_miles,may10_gas,'apr10',apr10_miles,apr10_gas,'mar10',mar10_miles,mar10_gas,'feb10',feb10_miles,feb10_gas,'jan10',jan10_miles,jan10_gas,'dec09',dec09_miles,dec09_gas,'nov09',nov09_miles,nov09_gas,'oct09',oct09_miles,oct09_gas,'sep09',sep09_miles,sep09_gas,'aug09',aug09_miles,aug09_gas,'jul09',jul09_miles,jul09_gas,'jun09',jun09_miles,jun09_gas,'may09',may09_miles,may09_gas,'apr09',apr09_miles,apr09_gas,'mar09',mar09_miles,mar09_gas,'feb09',feb09_miles,feb09_gas,'jan09',jan09_miles,jan09_gas ) dummyalias AS rdate, miles, gas;
select * from truck_mileage limit 100;
CREATE TABLE avg_mileage STORED AS ORC AS SELECT truckid, avg(mpg) avgmpg FROM truck_mileage GROUP BY truckid;
CREATE TABLE DriverMileage STORED AS ORC AS SELECT driverid, sum(miles) totmiles FROM truck_mileage GROUP BY driverid;
Hadoop高级脚本语言,在不需要java的情况下实现复杂的数据转换,包含类SQL的脚本语言Pig Latin。通过Pig中的User Defined Functions(UDF) 工具可做所有的数据操作。能调用JRuby, Jython and Java等语言。也能在其他语言中嵌入Pig脚本。也就是能把Pig作为一个组件来建立大型复杂的应用。可作用于结构化和非结构化数据,将结果存储于HDFS。
Pig脚本会转换为一系列的MR jobs在集群中运行。
例如:使用Pig来计算每位司机的风险因素。执行Pig代码之前,必须在Hive建立好表来满足HCatStorer()
类的要求。
#Hive中通过DDL建表:
CREATE TABLE riskfactor (driverid string, events bigint, totmiles bigint, riskfactor float) STORED AS ORC;
使用HCatalog加载数据到Pig中。它还允许我们从查询和脚本中分解出模式和位置信息,并将他们集中到一个库中。可将其用于HCatLoader() 函数。我们可以只给它表名或者别名,而不用进行空间的分配和结构的定义。只用在意如何处理表。
a = LOAD 'geolocation' USING org.apache.hive.hcatalog.pig.HCatLoader();
#结果保存于a
过滤数据:
b = filter a by event != 'normal';
迭代数据,如获取非正常事件司机的数量:
c = foreach b generate driverid, event, (int) '1' as occurance;
计算每个司机的非正常事件总数:
d = group c by driverid;
e = foreach d generate group as driverid, SUM(c.occurance) as t_occ;
加载DRIVERMILEAGE 表,执行join,得到一个司机的总里程数和总非正常事件:
g = LOAD 'drivermileage' using org.apache.hive.hcatalog.pig.HCatLoader();
h = join e by driverid, g by driverid;
计算司机危险因子并存储:
final_data = foreach h generate $0 as driverid, $1 as events, $3 as totmiles, (float) $3/$1 as riskfactor;
store final_data into 'riskfactor' using org.apache.hive.hcatalog.pig.HCatStorer();
最终脚本:
# 从HCatalog中加载geolocation表
a = LOAD 'geolocation' using org.apache.hive.hcatalog.pig.HCatLoader();
# 过滤出非正常数据
b = filter a by event != 'normal';
# 添加一列计数发生次数
c = foreach b generate driverid, event, (int) '1' as occurance;
# 按司机分组并计算每个司机的非正常事件发生次数
d = group c by driverid;
e = foreach d generate group as driverid, SUM(c.occurance) as t_occ;
# 加载Hive中创建的里程数据
g = LOAD 'drivermileage' using org.apache.hive.hcatalog.pig.HCatLoader();
# 事件计数和里程数据进行连接
h = join e by driverid, g by driverid;
# 计算多少里程发生一个非正常事件
final_data = foreach h generate $0 as driverid, $1 as events, $3 as totmiles, (float) $3/$1 as riskfactor;
store final_data into 'riskfactor' using org.apache.hive.hcatalog.pig.HCatStorer();
点击Save保存脚本riskfactor.pig
注意:必须添加配置Pig编辑器,才能成功加载相关libraries,要区分大小写
内存计算平台,支持scala,java,python,r的api。
本例用于计算风险
为了与Hive更好的集成,spark已经支持ORC文件。HiveContext是spark SQL执行引擎的一个实例。SQLContext提供了spark SQL支持,它从classpath下的hive-site.xml文件读取Hive配置信息。
在Zeppelin notebook中写入
%jdbc(hive) show tables
执行
丢弃上一节创建的riskfactor表
%jdbc(hive) drop table riskfactor
%spark2
val hiveContext = new org.apache.spark.sql.SparkSession.Builder().getOrCreate()
spark核心弹性分布式数据集,采用分布式的数据集合进行并行处理。
创建RDD 的三种方式:
1. 并行化处理一个已经存在在SPARK中的数据集;
2. 通过引用一个数据集来创建RDD,这个数据集可来自于hfds,Cassandra,hbase等;
3. 改变一个已经存在的RDD来创建新的RDD。
加载数据对RDD进行实例化后,可进行两类操作:
1. 转换(Transformation):通过一个已经存在的RDD来创建新的数据集,并建立可用于分割的数据集的DAG(有向无环图),转换不返回值;
2. 动作(Action):执行一个DAG并返回一个值。
%spark2
hiveContext.sql("show tables").show()
%spark2
val geolocation_temp1 = hiveContext.sql("select * from geolocation") %spark2 val drivermileage_temp1 = hiveContext.sql("select * from drivermileage")
%spark2
geolocation_temp1.createOrReplaceTempView("geolocation_temp1")
drivermileage_temp1.createOrReplaceTempView("drivermileage_temp1")
hiveContext.sql("show tables").show()
过滤非正常事件的司机,并对每位司机的非正常事件进行计数。
%spark2
val geolocation_temp2 = hiveContext.sql("SELECT driverid, count(driverid) occurance from geolocation_temp1 where event!='normal' group by driverid")
%spark2
geolocation_temp2.createOrReplaceTempView("geolocation_temp2")
hiveContext.sql("show tables").show()
执行一个RDD动作来查看结果:
%spark2
geolocation_temp2.show(10)
得到每位司机的总里程和总非正常事件数
%spark2
val joined = hiveContext.sql("select a.driverid,a.occurance,b.totmiles from geolocation_temp2 a,drivermileage_temp1 b where a.driverid=b.driverid")
%spark2
joined.createOrReplaceTempView("joined")
hiveContext.sql("show tables").show()
执行RDD动作查看结果:
%spark2
joined.show(10)
%spark2
val risk_factor_spark = hiveContext.sql("select driverid, occurance, totmiles, totmiles/occurance riskfactor from joined")
%spark2
risk_factor_spark.createOrReplaceTempView("risk_factor_spark")
hiveContext.sql("show tables").show()
%spark2
risk_factor_spark.show(10)
%spark2
hiveContext.sql("create table finalresults( driverid String, occurance bigint, totmiles bigint, riskfactor double) stored as orc").toDF() hiveContext.sql("show tables").show()
%spark2
risk_factor_spark.write.format("orc").save("risk_factor_spark")
%spark2
hiveContext.sql("load data inpath 'risk_factor_spark' into table finalresults")
%spark
hiveContext.sql("create table riskfactor as select * from finalresults").toDF()
使用Apache Zeppelin可视化数据
浏览器打开界面:
http://sandbox.hortonworks.com:9995
展示前节所创建的数据
1. 在Zeppelin note
中写查询
%jdbc(hive)
SELECT * FROM riskfactor