大数据物流项目:主题及报表开发(十二)

举报
Maynor学长 发表于 2022/06/29 20:40:05 2022/06/29
【摘要】 theme: smartblue持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情 Logistics_Day12:主题及报表开发 01-[复习]-上次课程内容回顾​ 主要讲解2个方面内容:==离线报表分析(SparkSQL)和即席查询分析(Impala)==,数据都存储在Kudu数据库中,结构化流程序实时消费Kafka数据,ETL转换后存储到...

theme: smartblue

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

Logistics_Day12:主题及报表开发

1613867341272

01-[复习]-上次课程内容回顾

​ 主要讲解2个方面内容:==离线报表分析(SparkSQL)和即席查询分析(Impala)==,数据都存储在Kudu数据库中,结构化流程序实时消费Kafka数据,ETL转换后存储到Kudu表中。

  • ==1)、离线报表分析==

    • 技术框架(分析引擎):SparkSQL,数据结构DataFrame/Dataset
    • 按照数据仓库分层管理数据:三层架构(ODS、DWD、DWS),便于管理数据和开发使用
    • 依据主题划分业务报表,每个主题报表开发,需要2步操作:
      • 第一步、事实表(业务数据表)与相关维度表数据进行关联拉宽操作,DWD层
      • 第二步、对宽表数据按照业务指标进行计算,DWS层
    • 公共接口BasicOfflineApp,提供三个方法:load加载数据、process处理数据和save保存数据

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6guAQyL2-1641191197136)(/img/1616375483879.png)]

1613962944032

​ 每个主题报表分析时,先进行数据拉宽操作,再进行指标计算。其中指标计算,按照日期day划分数据,对每日业务数据进行分析统计,封装到Row对象中,最后将分析指标转换DataFrame进行返回。

1613962957638

  • 2)、==即席查询分析(Ad Hoc)==
    • 使用技术框架(分析引擎):Impala 基于内存分析引擎
    • SQL on Hadoop 技术框架发展史(Hive:HDFS和HBase -> Impala:HDFS和HBase -> Impala:Kudu
    • Impala 与Hive框架比较:取代Hive,使用内存进行分布式查询分析;依赖Hive MetaStore管理元数据
    • Impala 服务架构(三个组件)
      • Impalad服务(守护进程),主要接收SQL语句,转换查询计划,分发计划任务,执行任务,收集结果给Client返回。
        • QueryPlanner、QueryCoordinator、QueryExecutor
      • StateStored服务,同步集群中所有Impalad服务状态到所有Impalad服务
      • Catalogd服务,同步元数据到所有Impalad服务,启动时加载HiveMetaStore元数据
    • Impala分析引擎提供交互式命令:impala-shell,可以直接连接impalad服务
    • Impala如何查询分析数据流程

1613896374570

  • 如何使用Impala集成Kudu创建表,有2种方式:管理表和外部表(推荐使用)
  • Hue与Impala集成,提供SQL编写界面,底层使用Impala分析数据。

02-[了解]-第12天:课程内容提纲

主要讲解:离线报表数据分析(2个主题:运单主题(讲解)仓库主题(作业))。

  • 1)、离线报表分析,按照主题topic划分业务报表
    • 每个主题报表开发,按照数据仓库分层管理数据和开发指标,需要编写2个SparkSQL应用
      • DWD层:数据拉宽,将事实表数据与维度表数据进行关联,leftJoin(大表在左,小表在右)
      • DWS层:指标计算,加载宽表数据按照指标需求进行计算,按照每天数据进行指标计算
  • 重构公共接口:BasicOfflineApp,使用模板方法(Template)设计模式重构接口
    • load加载数据、process处理数据和save保存数据

1614042929181

  • 3)、Kudu 原理和优化
  • Kudu数据存储引擎,类似HBase表,Kudu底层数据存储原理结构
  • 使用Kudu时注意事项和优化设置

03-[理解]-运单主题之数据调研及业务分析

​ 在物流快递行业,除了快递单(tbl_express_bill)主要业务数据以外,就是运单(tbl_waybill)数据

1614044001296

​ “运单是运输合同的证明,是承运人已经接收货物的收据。一份运单,填写托运人、收货人、起运港、到达港。如同一托运人的货物分别属到达港的两个或两个以上收货人,则应分别填制运单。”

​ 运单统计根据区域Area、公司Company、网点Dot、线路Route、运输工具Tool等维度进行统计,可以对各个维度运单数量进行排行,如对网点运单进行统计可以反映该网点的运营情况,对线路运单进行统计可以观察每个线路的运力情况。

  • 1)、运单主题指标

1616378623511

1616378639284

按照6个维度统计运单数量及最大、最小和平均运单数。

  • 2)、业务数据(事实表数据)

1616378705865

  • 3)、维度表

1616378852556

  • 4)、事实表与维度表关联关系图

1616378866761

可以按照主题报表开发步骤进行编码:数据拉宽(DWD层)和指标计算(DWS层)。

04-[掌握]-主题及指标开发之重构公共接口【思路】

前面对【快递单】数据进行指标开发,但是发现问题,有大量代码重复,尤其DWD层和DWS层中MAIN方法:

  • 1)、快递单:DWD层程序【MAIN方法】

1616379126981

  • 2)、快递单:DWS层程序【MAIN方法】

1616379138139

​ 发现2个MAIN方法中,步骤几乎一样的(step1、step2、step3、….),只不过是传递参数不一样而已(比如加载数据时表的名称不一样、处理数据时数据集不一样、保存数据时数据集不一样等),所以可以考虑重构公共接口,采用模板方法设计模式Template Parttern,将main方法中代码封装到方法:execute,传递不同参数即可。

模板方法模式(Template Pattern),是一种类继承模式,主要是==通过一个抽象类,把子类一些共有的类提取出来(称为基本方法)放到抽象类中,并在抽象类中定义一个模板方法,在模板方法中规定基本方法的执行顺序==。将不同的实现细节交给子类去实现。

1616379483662

模板方法设计模式使用场景:

1616379554837

案例说明:小明和小华去学校上学前准备工作(叠被子、吃早餐和去学校)

1616379665319

==假设重构接口:AbstractOfflineApp,其中方法如下所示:==

  • 将SparkSession会话实例创建和关闭,分别封装到不同方法中(基本方法),可以具体实现
  • 定义模板方法:execute,规定基本方法执行顺序,将mian方法中代码移到此方法中,调用方法时桉树进行传递即可。

1614045318315

package cn.itcast.logistics.offline

import org.apache.spark.sql.{DataFrame, SparkSession}

trait AbstractOfflineApp {

	// 定义变量
	private var spark: SparkSession = _
	
	// 实例化spark对象
	def init(clazz: Class[_]): Unit = {
		
	}
	
	// 从Kudu表加载数据
	def loadKuduSource(spark: SparkSession, tableName: String, isLoadFull: Boolean = false): DataFrame = ???
	
	// 处理数据,要么是数据拉宽,要么是指标计算
	def process(dataframe: DataFrame): DataFrame
	
	// 保存数据到Kudu表
	def saveKuduSink(dataframe: DataFrame, tableName: String, keys: Seq[String] = Seq("id"))
	
	// 关闭会话实例对象
	def close(): Unit = {
		
	}
	
	// TODO: 定义模块方法,规定基本方法执行顺序
	def execute(clazz: Class[_], 
	            srcTable: String, isLoadFull: Boolean = false,
	            dstTable: String, keys: Seq[String] = Seq("id")): Unit = {
		// step1. 初始化
		init(clazz)
		try{
			// step2. 加载Kudu表数据
			val kuduDF: DataFrame = loadKuduSource(spark, srcTable, isLoadFull)
			kuduDF.show(10, truncate = false)
		
			// step3. 处理数据
			val resultDF: DataFrame = process(kuduDF)
			resultDF.show(10, truncate = false)
			
			// step4. 保存数据
			saveKuduSink(resultDF, dstTable, keys)
		}catch {
			case e: Exception => e.printStackTrace()
		}finally {
			// step5. 关闭资源
			close()
		}
	}
	
}

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。