大数据电商数仓项目--实战(一)数据准备

第一章 数仓分层

1.1 为什么要分层

在这里插入图片描述

1.2 数仓命名规范

1.2.1 表命名

  • ODS层命名为ods_表名
  • DIM层命名为dim_表名
  • DWD层命名为dwd_表名
  • DWS层命名为dws_表名
  • DWT层命名为dwt_表名
  • ADS层命名为ads_表名
  • 临时表命名为tmp_表名

1.2.2 表字段类型

  • 数量类型为bigint
  • 金额类型为decimal(16, 2),表示:16位有效数字,其中小数部分2位
  • 字符串(名字,描述信息等)类型为string
  • 主键外键类型为string
  • 时间戳类型为bigint

第二章 数仓理论

2.1 范式理论

2.1.1 范式概念

  1. 定义 : 数据建模必须遵循一定的规则,在关系数建模中,这种规则就是范式
  2. 优点 : 采用范式,可以减低数据的冗余性
  3. 缺点 : 范式的缺点是获取数据时,需要通过join拼接处最后的数据

2.1.2函数依赖

在这里插入图片描述

2.1.3三范式区分

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2 关系建模和维度建模

2.2.1 关系建模

关系建模将复杂的数据抽象为两个概念——实体和关系,并使用规范化的方式表示出来。关系模型严格遵循第三范式(3NF),数据冗余程度低,数据的一致性容易得到保证。由于数据分布于众多的表中,查询会相对复杂,在大数据的场景下,查询效率相对较低。

2.2.2 维度建模

维度模型以数据分析作为出发点,不遵循三范式,故数据存在一定的冗余。维度模型面向业务,将业务用事实表和维度表呈现出来。表结构简单,故查询简单,查询效率较高。

2.3 维度表和事实表(重点)

2.3.1维度表:

一般是对事物的描述信息。每一张维度表对应现实世界中的一个对象或者概念,例如:用户,商品,日期,地区等
维度表的特征: 维度表的范围很宽(具有多个属性,列)跟事实表相比行数较少,内容相对固定
如时间维度表:
在这里插入图片描述

2.3.2 事实表:

事实表中的每行数据代表一个业务事件(下单、支付、退款、评价等)。“事实”这个术语表示的是业务事件的度量值(可统计次数、个数、金额等),例如,2020年5月21日,宋宋老师在京东花了250块钱买了一瓶海狗人参丸。维度表:时间、用户、商品、商家。事实表:250块钱、一瓶
事实表的特征:非常的大,内容相对的窄:列数较少(主要是外键id和度量值),经常发生变化,每天会新增加很多。

2.4 维度模型分析

维度模型基础上分为3种模型:星型模型,雪花模型,星座模型
在这里插入图片描述

2.5 数据仓库建模(重点)

2.5.1 ODS层

  1. hdfs用户行为数据
    在这里插入图片描述
  2. hdfs业务数据
    在这里插入图片描述
  3. 针对hdfs上用户的行为数据和业务数据,我们如何规划处理
  • 保持数据原貌不做任何修改,起到备份数据的作用
  • 数据采用压缩,减少磁盘存储空间
  • 创建分区表,防止后续全表扫描

DIM层和DWD层

DIM层和DWD层需构建维度模型,一般采用星型模型,呈现的状态一般为星座模型
维度建模一般按照以下四个步骤:
选择业务过程=>声明粒度=>确认维度=>确认事实
(1)选择业务过程
在业务系统中,挑选我们感兴趣的业务线,比如下单业务,支付业务,退款业务,物流业务,一条业务线对应一张事实表。
(2)声明粒度
数据粒度指数据仓库的数据中保存数据的细化程度或综合程度的级别。
声明粒度意味着精确定义事实表中的一行数据表示什么,应该尽可能选择最小粒度,以此来应各种各样的需求。
典型的粒度声明如下:
订单事实表中一行数据表示的是一个订单中的一个商品项。
支付事实表中一行数据表示的是一个支付记录。
(3)确定维度
维度的主要作用是描述业务是事实,主要表示的是“谁,何处,何时”等信息。
确定维度的原则是:后续需求中是否要分析相关维度的指标。例如,需要统计,什么时间下的订单多,哪个地区下的订单多,哪个用户下的订单多。需要确定的维度就包括:时间维度、地区维度、用户维度。
(4)确定事实
此处的“事实”一词,指的是业务中的度量值(次数、个数、件数、金额,可以进行累加),例如订单金额、下单次数等。
在这里插入图片描述至此,数据仓库的维度建模已经完毕,DWD层是以业务过程为驱动。

2.5.3DWS层与DWT层

DWS层和DWT层统称宽表层,这两层的设计思想大致相同,通过以下案例进行阐述。
1)问题引出:两个需求,统计每个省份订单的个数、统计每个省份订单的总金额
2)处理办法:都是将省份表和订单表进行join,group by省份,然后计算。同样数据被计算了两次,实际上类似的场景还会更多。
那怎么设计能避免重复计算呢?
针对上述场景,可以设计一张地区宽表,其主键为地区ID,字段包含为:下单次数、下单金额、支付次数、支付金额等。上述所有指标都统一进行计算,并将结果保存在该宽表中,这样就能有效避免数据的重复计算。
DWS和DWT层的区别:DWS层存放的所有主题对象当天的汇总行为,例如每个地区当天的下单次数,下单金额等,DWT层存放的是所有主题对象的累积行为,例如每个地区最近7天(15天、30天、60天)的下单次数、下单金额等。
总之:DWS和DWT层其实是计算的结果,目的就是为了防止用的时候重复计算

2.5.4 ADS层

对电商系统各大主题指标分别进行分析。

第三章 数仓环境搭建

3.1 Hive 环境搭建

3.1.1 Hive引擎简介

Hive 引擎包括:默认MR ,tez ,spark
Hive on Spark 既作为 存储 元数据 又负责 SQL的解析优化 语法是HQL语法
Spark on Hive :Hive只作为存储元数据,Spark 负责SQL解析优化 语法是Spark SQL语法

3.1.2 Hive on Spark配置

1)兼容性说明
注意:官网下载的Hive3.1.2和Spark3.0.0默认是不兼容的。因为Hive3.1.2支持的Spark版本是2.4.5,所以需要我们重新编译Hive3.1.2版本。
编译步骤:官网下载Hive3.1.2源码,修改pom文件中引用的Spark版本为3.0.0,如果编译通过,直接打包获取jar包。如果报错,就根据提示,修改相关方法,直到不报错,打包获取jar包。

2)在Hive所在节点部署Spark

(2)上传并解压解压spark-3.0.0-bin-hadoop3.2.tgz
(3)配置SPARK_HOME环境变量
3)在hive中创建spark配置文件
vim /opt/module/hive/conf/spark-defaults.conf
添加如下内容(在执行任务时,会根据如下参数执行)

spark.master                               yarn
spark.eventLog.enabled                   true
spark.eventLog.dir                        hdfs://hadoop102:8020/spark-history
spark.executor.memory                    1g
spark.driver.memory					   1g

在HDFS创建如下路径,用于存储历史日志
hdfs dfs -mkdir /spark-history
4)向HDFS上传Spark纯净版jar包
说明1:由于Spark3.0.0非纯净版默认支持的是hive2.3.7版本,直接使用会和安装的Hive3.1.2出现兼容性问题。所以采用Spark纯净版jar包,不包含hadoop和hive相关依赖,避免冲突。
说明2:Hive任务最终由Spark来执行,Spark任务资源分配由Yarn来调度,该任务有可能被分配到集群的任何一个节点。所以需要将Spark的依赖上传到HDFS集群路径,这样集群中任何一个节点都能获取到。
(1)上传并解压spark-3.0.0-bin-without-hadoop.tgz
tar -zxvf /opt/software/spark-3.0.0-bin-without-hadoop.tgz
(2)上传Spark纯净版jar包到HDFS
hafs dfs -mkdir /spark-jars
hdfs dfs -put spark-3.0.0-bin-without-hadoop/jars/* /spark-jars
5)修改hive-site.xml文件
vim /opt/module/hive/conf/hive-site.xml
添加如下内容

<!--Spark依赖位置(注意:端口号8020必须和namenode的端口号一致)-->
<property><name>spark.yarn.jars</name><value>hdfs://hadoop102:8020/spark-jars/*</value>
</property><!--Hive执行引擎-->
<property><name>hive.execution.engine</name><value>spark</value>
</property><!--Hive和Spark连接超时时间-->
<property><name>hive.spark.client.connect.timeout</name><value>10000ms</value>
</property>\```## 3.2Yarn配置
### 3.2.1 增加ApplicationMaster资源比例
容量调度器对每个资源队列中同时运行的Application Master占用的资源进行了限制,该限制通过yarn.scheduler.capacity.maximum-am-resource-percent参数实现,其默认值是0.1,表示每个资源队列上Application Master最多可使用的资源为该队列总资源的10%,目的是防止大部分资源都被Application Master占用,而导致Map/Reduce Task无法执行。
生产环境该参数可使用默认值。但学习环境,集群资源总数很少,如果只分配10%的资源给Application Master,则可能出现,同一时刻只能运行一个Job的情况,因为一个Application Master使用的资源就可能已经达到10%的上限了。故此处可将该值适当调大。
1. 在hadoop102的/opt/module/hadoop-3.1.3/etc/hadoop/capacity-scheduler.xml文件中修改如下参数值
```bash
<property><name>yarn.scheduler.capacity.maximum-am-resource-percent</name><value>0.8</value>
</property
  1. 分发capacity-scheduler.xml配置文件
  2. 关闭正在运行的任务,重新启动yarn集群

3.3 数仓开发环境

数仓开发工具可选用DBeaver或者DataGrip。两者都需要用到JDBC协议连接到Hive,故需要启动HiveServer2。
1.启动HiveServer2
bin/hiveserver2
2 .创建连接
在这里插入图片描述
3. 配置连接属性
在这里插入图片描述
4. 测试使用
1)创建数据库
在这里插入图片描述
2)修改连接,指明连接数据库
在这里插入图片描述
4)选择当前数据库为gmall

3.4 数据准备

一般企业在搭建数仓时,业务系统中会存在一定的历史数据,此处为模拟真实场景,需准备若干历史数据。假定数仓上线的日期为2020-06-14,具体说明如下。
1.用户行为日志
用户行为日志,一般是没有历史数据的,故日志只需要准备2020-06-14一天的数据。具体操作如下:
1)启动日志采集通道,包括Flume、Kafak等
2)修改两个日志服务器(hadoop102、hadoop103)中的/opt/module/applog/application.yml配置文件,将mock.date参数改为2020-06-14。
3)执行日志生成脚本lg.sh。
4)观察HDFS是否出现相应文件。
2.业务数据
业务数据一般存在历史数据,此处需准备2020-06-10至2020-06-14的数据。具体操作如下。
1)修改hadoop102节点上的/opt/module/db_log/application.properties文件,将mock.date、mock.clear,mock.clear.user三个参数调整为如图所示的值。
在这里插入图片描述
2)执行模拟生成业务数据的命令,生成第一天2020-06-10的历史数据。

java -jar gmall2020-mock-db-2021-01-22.jar

3)修改/opt/module/db_log/application.properties文件,将mock.date、mock.clear
在这里插入图片描述
4)执行模拟生成业务数据的命令,生成第二天2020-06-11的历史数据。
java -jar gmall2020-mock-db-2021-01-22.jar
5)之后只修改/opt/module/db_log/application.properties文件中的mock.date参数,依次改为2020-06-12,2020-06-13,2020-06-14,并分别生成对应日期的数据。
6)执行mysql_to_hdfs_init.sh脚本,将模拟生成的业务数据同步到HDFS。
mysql_to_hdfs_init.sh all 2020-06-14
7)观察HDFS上是否出现相应的数据
此处生成数据时,一定要确保生成的数据完整性,以防后面导入不必要的麻烦。

4.1 ODS层(用户行为数据)

4.1.1 创建日志表ods_log

在这里插入图片描述
1)创建支持snappy压缩的分区表

hive (gmall)> 
drop table if exists ods_log;
CREATE EXTERNAL TABLE ods_log (`line` string)
PARTITIONED BY (`dt` string) -- 按照时间创建分区
LOCATION '/warehouse/gmall/ods/ods_log'  -- 指定数据在hdfs上的存储位置

2)加载数据

hive (gmall)> 
load data inpath '/origin_data/gmall/log/topic_log/2020-06-14' into table ods_log partition(dt='2020-06-14');

注意:时间格式都配置成YYYY-MM-DD格式,这是Hive默认支持的时间格式

4.1.3 ODS层日志表加载数据脚本

1)编写脚本
vim hdfs_to_ods_log.sh

#!/bin/bash# 定义变量方便修改
APP=gmall# 如果是输入的日期按照取输入日期;如果没输入日期取当前时间的前一天
if [ -n "$1" ] ;thendo_date=$1
else do_date=`date -d "-1 day" +%F`
fi echo ================== 日志日期为 $do_date ==================
sql="
load data inpath '/origin_data/$APP/log/topic_log/$do_date' into table ${APP}.ods_log partition(dt='$do_date');
"
hive -e "$sql"

加上权限,然后执行脚本即可

4.2ODS层(业务数据)(重点)

在这里插入图片描述
确保安装sqoop并且先进行测试,此处我在学习过程中导入时,遇到了很多问题,基本上都是sqoop命令导入的问题。所以提前测试好会事半功倍

4.2.1首先是建表

由于代码较多,此处略过,需要的可以私信咨询

4.2.2 数据装载(将hdfs中的业务数据加载到hive数仓中)

1)编写装载脚本
vim hdfs_to_ods_db.sh

#!/bin/bashAPP=gmall# 如果是输入的日期按照取输入日期;如果没输入日期取当前时间的前一天
if [ -n "$2" ] ;thendo_date=$2
else do_date=`date -d "-1 day" +%F`
fiods_order_info=" 
load data inpath '/origin_data/$APP/db/order_info/$do_date' OVERWRITE into table ${APP}.ods_order_info partition(dt='$do_date');"ods_order_detail="
load data inpath '/origin_data/$APP/db/order_detail/$do_date' OVERWRITE into table ${APP}.ods_order_detail partition(dt='$do_date');"ods_sku_info="
load data inpath '/origin_data/$APP/db/sku_info/$do_date' OVERWRITE into table ${APP}.ods_sku_info partition(dt='$do_date');"ods_user_info="
load data inpath '/origin_data/$APP/db/user_info/$do_date' OVERWRITE into table ${APP}.ods_user_info partition(dt='$do_date');"ods_payment_info="
load data inpath '/origin_data/$APP/db/payment_info/$do_date' OVERWRITE into table ${APP}.ods_payment_info partition(dt='$do_date');"ods_base_category1="
load data inpath '/origin_data/$APP/db/base_category1/$do_date' OVERWRITE into table ${APP}.ods_base_category1 partition(dt='$do_date');"ods_base_category2="
load data inpath '/origin_data/$APP/db/base_category2/$do_date' OVERWRITE into table ${APP}.ods_base_category2 partition(dt='$do_date');"ods_base_category3="
load data inpath '/origin_data/$APP/db/base_category3/$do_date' OVERWRITE into table ${APP}.ods_base_category3 partition(dt='$do_date'); "ods_base_trademark="
load data inpath '/origin_data/$APP/db/base_trademark/$do_date' OVERWRITE into table ${APP}.ods_base_trademark partition(dt='$do_date'); "ods_activity_info="
load data inpath '/origin_data/$APP/db/activity_info/$do_date' OVERWRITE into table ${APP}.ods_activity_info partition(dt='$do_date'); "ods_cart_info="
load data inpath '/origin_data/$APP/db/cart_info/$do_date' OVERWRITE into table ${APP}.ods_cart_info partition(dt='$do_date'); "ods_comment_info="
load data inpath '/origin_data/$APP/db/comment_info/$do_date' OVERWRITE into table ${APP}.ods_comment_info partition(dt='$do_date'); "ods_coupon_info="
load data inpath '/origin_data/$APP/db/coupon_info/$do_date' OVERWRITE into table ${APP}.ods_coupon_info partition(dt='$do_date'); "ods_coupon_use="
load data inpath '/origin_data/$APP/db/coupon_use/$do_date' OVERWRITE into table ${APP}.ods_coupon_use partition(dt='$do_date'); "ods_favor_info="
load data inpath '/origin_data/$APP/db/favor_info/$do_date' OVERWRITE into table ${APP}.ods_favor_info partition(dt='$do_date'); "ods_order_refund_info="
load data inpath '/origin_data/$APP/db/order_refund_info/$do_date' OVERWRITE into table ${APP}.ods_order_refund_info partition(dt='$do_date'); "ods_order_status_log="
load data inpath '/origin_data/$APP/db/order_status_log/$do_date' OVERWRITE into table ${APP}.ods_order_status_log partition(dt='$do_date'); "ods_spu_info="
load data inpath '/origin_data/$APP/db/spu_info/$do_date' OVERWRITE into table ${APP}.ods_spu_info partition(dt='$do_date'); "ods_activity_rule="
load data inpath '/origin_data/$APP/db/activity_rule/$do_date' OVERWRITE into table ${APP}.ods_activity_rule partition(dt='$do_date');" ods_base_dic="
load data inpath '/origin_data/$APP/db/base_dic/$do_date' OVERWRITE into table ${APP}.ods_base_dic partition(dt='$do_date'); "ods_order_detail_activity="
load data inpath '/origin_data/$APP/db/order_detail_activity/$do_date' OVERWRITE into table ${APP}.ods_order_detail_activity partition(dt='$do_date'); "ods_order_detail_coupon="
load data inpath '/origin_data/$APP/db/order_detail_coupon/$do_date' OVERWRITE into table ${APP}.ods_order_detail_coupon partition(dt='$do_date'); "ods_refund_payment="
load data inpath '/origin_data/$APP/db/refund_payment/$do_date' OVERWRITE into table ${APP}.ods_refund_payment partition(dt='$do_date'); "ods_sku_attr_value="
load data inpath '/origin_data/$APP/db/sku_attr_value/$do_date' OVERWRITE into table ${APP}.ods_sku_attr_value partition(dt='$do_date'); "ods_sku_sale_attr_value="
load data inpath '/origin_data/$APP/db/sku_sale_attr_value/$do_date' OVERWRITE into table ${APP}.ods_sku_sale_attr_value partition(dt='$do_date'); "ods_base_province=" 
load data inpath '/origin_data/$APP/db/base_province/$do_date' OVERWRITE into table ${APP}.ods_base_province;"ods_base_region="
load data inpath '/origin_data/$APP/db/base_region/$do_date' OVERWRITE into table ${APP}.ods_base_region;"case $1 in"ods_order_info"){hive -e "$ods_order_info"};;"ods_order_detail"){hive -e "$ods_order_detail"};;"ods_sku_info"){hive -e "$ods_sku_info"};;"ods_user_info"){hive -e "$ods_user_info"};;"ods_payment_info"){hive -e "$ods_payment_info"};;"ods_base_category1"){hive -e "$ods_base_category1"};;"ods_base_category2"){hive -e "$ods_base_category2"};;"ods_base_category3"){hive -e "$ods_base_category3"};;"ods_base_trademark"){hive -e "$ods_base_trademark"};;"ods_activity_info"){hive -e "$ods_activity_info"};;"ods_cart_info"){hive -e "$ods_cart_info"};;"ods_comment_info"){hive -e "$ods_comment_info"};;"ods_coupon_info"){hive -e "$ods_coupon_info"};;"ods_coupon_use"){hive -e "$ods_coupon_use"};;"ods_favor_info"){hive -e "$ods_favor_info"};;"ods_order_refund_info"){hive -e "$ods_order_refund_info"};;"ods_order_status_log"){hive -e "$ods_order_status_log"};;"ods_spu_info"){hive -e "$ods_spu_info"};;"ods_activity_rule"){hive -e "$ods_activity_rule"};;"ods_base_dic"){hive -e "$ods_base_dic"};;"ods_order_detail_activity"){hive -e "$ods_order_detail_activity"};;"ods_order_detail_coupon"){hive -e "$ods_order_detail_coupon"};;"ods_refund_payment"){hive -e "$ods_refund_payment"};;"ods_sku_attr_value"){hive -e "$ods_sku_attr_value"};;"ods_sku_sale_attr_value"){hive -e "$ods_sku_sale_attr_value"};;"all"){hive -e "$ods_order_info$ods_order_detail$ods_sku_info$ods_user_info$ods_payment_info$ods_base_category1$ods_base_category2$ods_base_category3$ods_base_trademark$ods_activity_info$ods_cart_info$ods_comment_info$ods_coupon_info$ods_coupon_use$ods_favor_info$ods_order_refund_info$ods_order_status_log$ods_spu_info$ods_activity_rule$ods_base_dic$ods_order_detail_activity$ods_order_detail_coupon$ods_refund_payment$ods_sku_attr_value$ods_sku_sale_attr_value"};;
esac

增加执行权限然后执行即可hdfs_to_ods_db.sh all 2020-06-14

第5章 数仓搭建-DIM层(重点)

5.1 商品维度表(全量)

在这里插入图片描述
1.建表语句

DROP TABLE IF EXISTS dim_sku_info;
CREATE EXTERNAL TABLE dim_sku_info (`id` STRING COMMENT '商品id',`price` DECIMAL(16,2) COMMENT '商品价格',`sku_name` STRING COMMENT '商品名称',`sku_desc` STRING COMMENT '商品描述',`weight` DECIMAL(16,2) COMMENT '重量',`is_sale` BOOLEAN COMMENT '是否在售',`spu_id` STRING COMMENT 'spu编号',`spu_name` STRING COMMENT 'spu名称',`category3_id` STRING COMMENT '三级分类id',`category3_name` STRING COMMENT '三级分类名称',`category2_id` STRING COMMENT '二级分类id',`category2_name` STRING COMMENT '二级分类名称',`category1_id` STRING COMMENT '一级分类id',`category1_name` STRING COMMENT '一级分类名称',`tm_id` STRING COMMENT '品牌id',`tm_name` STRING COMMENT '品牌名称',`sku_attr_values` ARRAY<STRUCT<attr_id:STRING,value_id:STRING,attr_name:STRING,value_name:STRING>> COMMENT '平台属性',`sku_sale_attr_values` ARRAY<STRUCT<sale_attr_id:STRING,sale_attr_value_id:STRING,sale_attr_name:STRING,sale_attr_value_name:STRING>> COMMENT '销售属性',`create_time` STRING COMMENT '创建时间'
) COMMENT '商品维度表'
PARTITIONED BY (`dt` STRING)
STORED AS ORC
LOCATION '/warehouse/gmall/dim/dim_sku_info/'
TBLPROPERTIES ("orc.compress"="snappy");

2.数据装载
在这里插入图片描述
装载

with
sku as
(selectid,price,sku_name,sku_desc,weight,is_sale,spu_id,category3_id,tm_id,create_timefrom ods_sku_infowhere dt='2020-06-14'
),
spu as
(selectid,spu_namefrom ods_spu_infowhere dt='2020-06-14'
),
c3 as
(selectid,name,category2_idfrom ods_base_category3where dt='2020-06-14'
),
c2 as
(selectid,name,category1_idfrom ods_base_category2where dt='2020-06-14'
),
c1 as
(selectid,namefrom ods_base_category1where dt='2020-06-14'
),
tm as
(selectid,tm_namefrom ods_base_trademarkwhere dt='2020-06-14'
),
attr as
(selectsku_id,collect_set(named_struct('attr_id',attr_id,'value_id',value_id,'attr_name',attr_name,'value_name',value_name)) attrsfrom ods_sku_attr_valuewhere dt='2020-06-14'group by sku_id
),
sale_attr as
(selectsku_id,collect_set(named_struct('sale_attr_id',sale_attr_id,'sale_attr_value_id',sale_attr_value_id,'sale_attr_name',sale_attr_name,'sale_attr_value_name',sale_attr_value_name)) sale_attrsfrom ods_sku_sale_attr_valuewhere dt='2020-06-14'group by sku_id
)
insert overwrite table dim_sku_info partition(dt='2020-06-14')
selectsku.id,sku.price,sku.sku_name,sku.sku_desc,sku.weight,sku.is_sale,sku.spu_id,spu.spu_name,sku.category3_id,c3.name,c3.category2_id,c2.name,c2.category1_id,c1.name,sku.tm_id,tm.tm_name,attr.attrs,sale_attr.sale_attrs,sku.create_time
from sku
left join spu on sku.spu_id=spu.id
left join c3 on sku.category3_id=c3.id
left join c2 on c3.category2_id=c2.id
left join c1 on c2.category1_id=c1.id
left join tm on sku.tm_id=tm.id
left join attr on sku.id=attr.sku_id
left join sale_attr on sku.id=sale_attr.sku_id;

此处有个两个常见的问题
我两次搭建数仓都出现了,在这里记录一下
第一个:
在这里插入图片描述
这个问题在我查资料之后解决,如果在搭建成功的情况下,执行某些较为复杂的命令时才报错。原因是hadoop/etc/hadoop/capacity-scheduler.xml中yarn.scheduler.capacity.maximum-am-resource-percent参数设置不对
application master资源比例,默认为0.1,如果该值设置过大,就会导致mapreduce时内存不足,就会报上面错误。如果该值是默认值,在学习环境下application master分配内存较少,可能同时只能执行一个job,影响效率。可以尝试调整0.5,我当时学习的时候就想当然的觉得越大越好,就调到了0.8,从0.8调至0.5,问题解决。所以这个问题也告诉我,不理解的内容就不要想当然的改动,还是要弄明白意思之后才能调整。
第二个:
Hive报错FAILED:Execution Error, return code 3 from org.apache.hadoop.hive.ql.exec.spark.SparkTask. Spark job failed during runtime. Please check stacktrace for the root cause.
这个错误是因为hive的map join参数默认是开启的:hive.auto.convert.join=true
MapJoin是指在Map 端进行join,其原理是broadcast join,即把小表作为一个完整的驱动表来进行join操作。通常情况下,要连接的各个表里面的数据会分布在不同的Map中进行处理。即同一个Key对应的Value可能存在不同的Map中。这样就必须等到 Reduce中去连接。要使MapJoin能够顺利进行,那就必须满足这样的条件:除了一份表的数据分布在不同的Map中外,其他连接的表的数据必须在每个Map中有完整的拷贝。Map Join会把小表全部读入内存中,在Map阶段直接拿另外一个表的数据和内存中表数据做匹配 (这时可以使用Distributed Cache将小表分发到各个节点上,以供Mapper加载使用),由于在map时进行了join操作,省去了reduce运行的效率也会高很多。

所以当机器内存不足时,无法在Map端进行join,即会报错
解决方法:修改配置文件下的参数可以把map join 关闭,使用common join ,修改hive-site.xml

<property>
<name>hive.auto.convert.join</name>
<value>false</value>//true修改为false
<description>Enables the optimization about converting common join into mapjoin</description>
</property>

5.2 优惠券维度表(全量)

在这里插入图片描述
1.建表语句

DROP TABLE IF EXISTS dim_coupon_info;
CREATE EXTERNAL TABLE dim_coupon_info(`id` STRING COMMENT '购物券编号',`coupon_name` STRING COMMENT '购物券名称',`coupon_type` STRING COMMENT '购物券类型 1 现金券 2 折扣券 3 满减券 4 满件打折券',`condition_amount` DECIMAL(16,2) COMMENT '满额数',`condition_num` BIGINT COMMENT '满件数',`activity_id` STRING COMMENT '活动编号',`benefit_amount` DECIMAL(16,2) COMMENT '减金额',`benefit_discount` DECIMAL(16,2) COMMENT '折扣',`create_time` STRING COMMENT '创建时间',`range_type` STRING COMMENT '范围类型 1、商品 2、品类 3、品牌',`limit_num` BIGINT COMMENT '最多领取次数',`taken_count` BIGINT COMMENT '已领取次数',`start_time` STRING COMMENT '可以领取的开始日期',`end_time` STRING COMMENT '可以领取的结束日期',`operate_time` STRING COMMENT '修改时间',`expire_time` STRING COMMENT '过期时间'
) COMMENT '优惠券维度表'
PARTITIONED BY (`dt` STRING)
STORED AS ORC
LOCATION '/warehouse/gmall/dim/dim_coupon_info/'
TBLPROPERTIES ("orc.compress"="snappy");

2.数据装载
在这里插入图片描述

insert overwrite table dim_coupon_info partition(dt='2020-06-14')
selectid,coupon_name,coupon_type,condition_amount,condition_num,activity_id,benefit_amount,benefit_discount,create_time,range_type,limit_num,taken_count,start_time,end_time,operate_time,expire_time
from ods_coupon_info
where dt='2020-06-14';

5.3 活动维度表(全量)

1.建表语句

DROP TABLE IF EXISTS dim_activity_rule_info;
CREATE EXTERNAL TABLE dim_activity_rule_info(`activity_rule_id` STRING COMMENT '活动规则ID',`activity_id` STRING COMMENT '活动ID',`activity_name` STRING  COMMENT '活动名称',`activity_type` STRING  COMMENT '活动类型',`start_time` STRING  COMMENT '开始时间',`end_time` STRING  COMMENT '结束时间',`create_time` STRING  COMMENT '创建时间',`condition_amount` DECIMAL(16,2) COMMENT '满减金额',`condition_num` BIGINT COMMENT '满减件数',`benefit_amount` DECIMAL(16,2) COMMENT '优惠金额',`benefit_discount` DECIMAL(16,2) COMMENT '优惠折扣',`benefit_level` STRING COMMENT '优惠级别'
) COMMENT '活动信息表'
PARTITIONED BY (`dt` STRING)
STORED AS ORC
LOCATION '/warehouse/gmall/dim/dim_activity_rule_info/'
TBLPROPERTIES ("orc.compress"="snappy");

在这里插入图片描述

2.数据装载

insert overwrite table dim_activity_rule_info partition(dt='2020-06-14')
selectar.id,ar.activity_id,ai.activity_name,ar.activity_type,ai.start_time,ai.end_time,ai.create_time,ar.condition_amount,ar.condition_num,ar.benefit_amount,ar.benefit_discount,ar.benefit_level
from
(selectid,activity_id,activity_type,condition_amount,condition_num,benefit_amount,benefit_discount,benefit_levelfrom ods_activity_rulewhere dt='2020-06-14'
)ar
left join
(selectid,activity_name,start_time,end_time,create_timefrom ods_activity_infowhere dt='2020-06-14'
)ai		
on ar.activity_id=ai.id;

5.4 地区维度表(特殊)

  1. 建表语句
DROP TABLE IF EXISTS dim_base_province;
CREATE EXTERNAL TABLE dim_base_province (`id` STRING COMMENT 'id',`province_name` STRING COMMENT '省市名称',`area_code` STRING COMMENT '地区编码',`iso_code` STRING COMMENT 'ISO-3166编码,供可视化使用',`iso_3166_2` STRING COMMENT 'IOS-3166-2编码,供可视化使用',`region_id` STRING COMMENT '地区id',`region_name` STRING COMMENT '地区名称'
) COMMENT '地区维度表'
STORED AS ORC
LOCATION '/warehouse/gmall/dim/dim_base_province/'
TBLPROPERTIES ("orc.compress"="snappy");
  1. 数据装载
insert overwrite table dim_base_province
selectbp.id,bp.name,bp.area_code,bp.iso_code,bp.iso_3166_2,bp.region_id,br.region_name
from ods_base_province bpjoin ods_base_region br on bp.region_id = br.id;

5.5 时间维度表(特殊)

  1. 建表语句
DROP TABLE IF EXISTS dim_date_info;
CREATE EXTERNAL TABLE dim_date_info(`date_id` STRING COMMENT '日',`week_id` STRING COMMENT '周ID',`week_day` STRING COMMENT '周几',`day` STRING COMMENT '每月的第几天',`month` STRING COMMENT '第几月',`quarter` STRING COMMENT '第几季度',`year` STRING COMMENT '年',`is_workday` STRING COMMENT '是否是工作日',`holiday_id` STRING COMMENT '节假日'
) COMMENT '时间维度表'
STORED AS ORC
LOCATION '/warehouse/gmall/dim/dim_date_info/'
TBLPROPERTIES ("orc.compress"="snappy");
  1. 数据装载
    通常情况下,时间维度表的数据并不是来自于业务系统,而是手动写入,并且由于时间维度表数据的可预见性,无须每日导入,一般可一次性导入一年的数据。
    1)创建临时表
DROP TABLE IF EXISTS tmp_dim_date_info;
CREATE EXTERNAL TABLE tmp_dim_date_info (`date_id` STRING COMMENT '日',`week_id` STRING COMMENT '周ID',`week_day` STRING COMMENT '周几',`day` STRING COMMENT '每月的第几天',`month` STRING COMMENT '第几月',`quarter` STRING COMMENT '第几季度',`year` STRING COMMENT '年',`is_workday` STRING COMMENT '是否是工作日',`holiday_id` STRING COMMENT '节假日'
) COMMENT '时间维度表'
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
LOCATION '/warehouse/gmall/tmp/tmp_dim_date_info/';

2)将数据文件上传到HFDS上临时表指定路径/warehouse/gmall/tmp/tmp_dim_date_info/
date_info.txt
3)执行以下语句将其导入时间维度表
insert overwrite table dim_date_info select * from tmp_dim_date_info;
4)检查数据是否导入成功
select * from dim_date_info;

5.6 用户维度表(拉链表)

5.6.1 拉链表概述

  1. 什么是拉链表:
    拉链表,记录每条信息的生命周期,一旦一条记录的生命周期结束,就重新开始一条新的记录,并把当前日期放入生效开始日期。
    如果当前日期至今有效就会在生效日期填入一个极大值(9999-99-99)
    在这里插入图片描述
  2. 为什么要做拉链表:
    因为用户信息不是一直都在改变的,所以每天做全量导入会使程序资源浪费,且效率低下
  3. 如何使用拉链表:
    通过生效开始日期<=某个日期 且生效结束日期>=某个日期,能够得到某个时间段的全量数据切片
    在这里插入图片描述
  4. 拉链表形成过程
    在这里插入图片描述

5.6.2 制作拉链表

  1. 建表语句
DROP TABLE IF EXISTS dim_user_info;
CREATE EXTERNAL TABLE dim_user_info(`id` STRING COMMENT '用户id',`login_name` STRING COMMENT '用户名称',`nick_name` STRING COMMENT '用户昵称',`name` STRING COMMENT '用户姓名',`phone_num` STRING COMMENT '手机号码',`email` STRING COMMENT '邮箱',`user_level` STRING COMMENT '用户等级',`birthday` STRING COMMENT '生日',`gender` STRING COMMENT '性别',`create_time` STRING COMMENT '创建时间',`operate_time` STRING COMMENT '操作时间',`start_date` STRING COMMENT '开始日期',`end_date` STRING COMMENT '结束日期'
) COMMENT '用户表'
PARTITIONED BY (`dt` STRING)
STORED AS ORC
LOCATION '/warehouse/gmall/dim/dim_user_info/'
TBLPROPERTIES ("orc.compress"="snappy");
  1. 数据装载
    在这里插入图片描述
    1)首日装载
    拉链表首日装载,需要进行初始化操作,具体工作为将截止到初始化当日的全部历史用户导入一次性导入到拉链表中。目前的ods_order_info表的第一个分区,即2020-06-14分区中就是全部的历史用户,故将该分区数据进行一定处理后导入拉链表的9999-99-99分区即可。
insert overwrite table dim_user_info partition(dt='9999-99-99')
selectid,login_name,nick_name,md5(name),md5(phone_num),md5(email),user_level,birthday,gender,create_time,operate_time,'2020-06-14','9999-99-99'
from ods_user_info
where dt='2020-06-14';
  1. 每日装载
    实现思路:
    在这里插入图片描述
    sql编写:
with
tmp as
(selectold.id old_id,old.login_name old_login_name,old.nick_name old_nick_name,old.name old_name,old.phone_num old_phone_num,old.email old_email,old.user_level old_user_level,old.birthday old_birthday,old.gender old_gender,old.create_time old_create_time,old.operate_time old_operate_time,old.start_date old_start_date,old.end_date old_end_date,new.id new_id,new.login_name new_login_name,new.nick_name new_nick_name,new.name new_name,new.phone_num new_phone_num,new.email new_email,new.user_level new_user_level,new.birthday new_birthday,new.gender new_gender,new.create_time new_create_time,new.operate_time new_operate_time,new.start_date new_start_date,new.end_date new_end_datefrom(selectid,login_name,nick_name,name,phone_num,email,user_level,birthday,gender,create_time,operate_time,start_date,end_datefrom dim_user_infowhere dt='9999-99-99')oldfull outer join(selectid,login_name,nick_name,md5(nick_name) nick_name,md5(name) name,md5(phone_num) phone_num,user_level,birthday,gender,create_time,operate_time,'2020-06-15' start_date,'9999-99-99' end_datefrom ods_user_infowhere dt='2020-06-15')newon old.id=new.id
)
insert overwrite table dim_user_info partition(dt)
selectnvl(new_id,old_id),nvl(new_login_name,old_login_name),nvl(new_nick_name,old_nick_name),nvl(new_name,old_name),nvl(new_phone_num,old_phone_num),nvl(new_email,old_email),nvl(new_user_level,old_user_level),nvl(new_birthday,old_birthday),nvl(new_gender,old_gender),nvl(new_create_time,old_create_time),nvl(new_operate_time,old_operate_time),nvl(new_start_date,old_start_date),nvl(new_end_date,old_end_date),nvl(new_end_date,old_end_date) dt
from tmp
union all
selectold_id,old_login_name,old_nick_name,old_name,old_phone_num,old_email,old_user_level,old_birthday,old_gender,old_create_time,old_operate_time,old_start_date,cast(date_add('2020-06-15',-1) as string),cast(date_add('2020-06-15',-1) as string) dt
from tmp
where new_id is not null and old_id is not null;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/433519.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电脑usb接口封禁如何实现?5种禁用USB接口的方法分享!(第一种你GET了吗?)

“防患于未然&#xff0c;安全始于细节。”在信息技术飞速发展的今天&#xff0c;企业的信息安全问题日益凸显。 USB接口作为数据传输的重要通道&#xff0c;在带来便利的同时&#xff0c;也成为了数据泄露和安全风险的高发地。 因此&#xff0c;对电脑USB接口进行封闭管理&a…

微服务的优点及在云原生时代的合理落地方式

云计算de小白 那么&#xff0c;微服务到底能给业务带来什么好处&#xff1f;在云原生时代&#xff0c;如何更合理地实现微服务&#xff1f; 架构没有好坏之分&#xff0c;只有适合与不适合。然而&#xff0c;当我们对比微服务架构与单体架构时&#xff0c;可以发现微服务有以…

8--苍穹外卖-SpringBoot项目中套餐管理 详解(二)

目录 删除套餐 需求分析和设计 代码开发 根据id查询套餐 mapper层 Service层 ServiceImpl层 Mapper层 批量删除套餐 mapper层 Service层 ServiceImpl层 Mapper层 SetmealMapper.xml 修改套餐 需求分析和设计 代码开发 起售停售套餐 需求分析和设计 代码开发…

Docker全家桶:从0到加载本地项目

安装docker&#xff0c;我们选择的是CentenOS 7。 目录 Docker安装 命令 命令别名 数据卷挂载 Dockerfile 容器网络互联 Docker安装 1. 先删除本机旧的或者残留的docker sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest …

前端——js基础

一、JavaScript &#xff08;简称js&#xff09;——js可以给网页实现一个动态效果 1.JavaScript 组成 - 核心语法 ECMScipt 简称(es): 规范js的基本语法 1.es是js的语法规范 管理者 2.js是es的实现 操作者 - DOM > 文档对象 提供js操作 (例如…

再也不用担心内容重复!在线伪原创工具,让创作更自由!

大家好&#xff0c;今天我们将讨论一个对网络写作非常有益的辅助工具——在线内容转换工具。不论您是需要更新您的博客&#xff0c;还是希望在社交平台上保持活跃&#xff0c;我们都频繁面临着迅速生成新内容的挑战。利用一个有效的工具来改写现有内容&#xff0c;可以极大地提…

什么是网络安全自动化以及优势与挑战

目录 网络安全自动化的工作原理 网络安全自动化的好处 增强的安全功能 改善表现和姿势 降低安全成本 简化的安全合规性和审计 更好的端点管理 网络安全自动化的挑战 耗时且容易出错的安全流程 可见性降低&#xff0c;风险和成本增加 合规管理 有用的网络安全自动化…

算法题之每日温度

每日温度 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;请在该位置用 0 来代替。 示例 1: 输入…

基于Java的建筑节能监测系统+能源管理+公共建筑能耗监测系统+建筑能耗监测系统+节能监测系统+能源管理系统

介绍 建筑节能监测系统是基于计算机网络、物联网、大数据和数据可视化等多种技术融合形成的一套节能监测系统 系统实现了对建筑电、水、热&#xff0c;气等能源、资源消耗情况的实时监测和预警、动态分析和评估&#xff0c;为用户建立了科学、系统的节能分析方法&#xff0c;…

14年408-计算机网络

第一题&#xff1a; 解析&#xff1a;OSI体系结构 OSI由下至上依次是&#xff1a;物理层-网络链路层-网络层-运输层-会话层-表示层-应用层。 因此直接为会话层提供服务的是运输层。答案选C 第二题&#xff1a; 解析&#xff1a;数据链路层-交换机的自学习和帧转发 主机a1向交换…

webshell-HTTP常见特征

一、总体特点 二、蚁剑 数据中可以看到一些明文字符串函数&#xff0c;响应中可以看到响应的明文数据。 ant特征以及对数据base64可以解码 chr类别的会出现大量的chr编码 大量的百分号字符 三、哥斯拉 第一个请求包很大 响应为0 密钥被拆分到数据前后 响应包cookie带&#xf…

C#和数据库高级:虚方法

文章目录 一、抽象方法和抽象类中的思考1.1、回顾抽象方法的特点1.2、针对抽象方法问题的引出 二、虚方法的使用步骤2.1、虚方法重写方法的调用2.2、系统自带的虚方法2.3、重写Equals方法2.4、虚方法和抽象方法的比较 三、虚方法和抽象方法的联系3.1、ToString()方法的应用 一、…

Python爬虫APP程序:构建智能化数据抓取工具

在信息爆炸的时代&#xff0c;数据的价值日益凸显。Python作为一种强大的编程语言&#xff0c;与其丰富的库一起&#xff0c;为爬虫程序的开发提供了得天独厚的优势。本文将探讨如何使用Python构建一个爬虫APP程序&#xff0c;以及其背后的思维逻辑。 什么是Python爬虫APP程序&…

php thinkphp 小程序发送订阅模板消息通知

小程序需要在我的模板中先选用模板 小程序需要先订阅模板 wx.requestSubscribeMessage({tmplIds: ["XII_0By8D9WabnUjVPB_8S1itsm2d4_xxx"],success:

springboot实战学习(7)(JWT令牌的组成、JWT令牌的使用与验证)

接着上篇博客的学习。上篇博客是在基本完成用户模块的注册接口的开发以及注册时的参数合法性校验的基础上&#xff0c;基本完成用户模块的登录接口的主逻辑以及提到了问题&#xff1a;"用户未登录&#xff0c;需要通过登录&#xff0c;获取到令牌进行登录认证&#xff0c;…

DRF实操学习——收货地址的设计

DRF实操学习——收货地址的设计 1.行政区划表的设计2. 行政区划表接口演示1.返回所有的省份2. 查询指定上级行政区划的所有子区划&#xff0c;以及展示自身区划 3.行政区划表接口重写补充&#xff1a;前端请求逻辑4. 优化5.收货地址的设计6. 收货地址表接口重写7.优化1. 优化返…

示例说明:elasticsearch实战应用

Elasticsearch 是一个基于 Lucene 的分布式搜索和分析引擎&#xff0c;广泛应用于日志分析、全文搜索、数据可视化等领域。以下是 Elasticsearch 实战应用的一些关键点和步骤&#xff1a; 1. 环境搭建 首先&#xff0c;你需要在你的环境中安装和配置 Elasticsearch。 安装 E…

一个 Java 语言简化处理 PDF 的框架,提供了一套简单易用的 API 接口,满足多样化需求又能简化开发流程的处理方案(附教程)

前言 当前市面上处理 PDF 文件的工具众多&#xff0c;但它们往往存在一定的局限性&#xff0c;比如复杂交互、功能单一等问题。尤其对于那些需要频繁生成或编辑 PDF 文档的应用场景来说&#xff0c;找到一个既能满足多样化需求又能简化开发流程的处理方案显得尤为重要。那么&a…

中国的互联网电商,终于还是“连上了”

什么才是更好的互联网&#xff1f; 答案很简单&#xff1a;真正的互联。 9月26日&#xff0c;据市场消息&#xff0c;京东物流和菜鸟速递将分别接入淘天、京东平台。同时&#xff0c;京东也将在“双11”前开通支付宝支付&#xff0c;时隔13年再度携手阿里支付体系。 消息一出…

【x**3专享#2】编译 uboot 和 kernel 的文件结构

虚拟机交叉编译环境配置及内核编译步骤说明书 请先查看前篇文章内容 1. 获取虚拟机 IP 地址 打开虚拟机终端&#xff0c;执行以下命令查看虚拟机 IP 地址&#xff1a;ifconfig或者ip addr记录 eth0 或 ens33 等网络接口的 inet 后面的 IP 地址 2. 使用 Xftp 连接虚拟机 打开…