一、准备数据

导入SQL如果报错了,设置一个全局变量:set global log_bin_trust_function_creators=TRUE;
导入SQL语句:

image.png
image.png
通过存储过程(类似于java代码中的方法),生成数据:
image.png
查看用户表信息中大约有几千条数据即可,不要太多,也不要太少。

二、分析一下项目

1、可以通过ER图,查看各个表关系(在有外键关联的情况下)
2、在公司中,一般都会数据库设计详细的文档。
分析的指标:
2022-04-21日当天,整个外卖平台,在家里,在学校,在公司的一个下单情况。
2022-04-21日当天,整个外卖平台,凌晨,早上,上午,中午,下午,晚上各个时间段的一个下单量。
想分析上面的指标,需要哪几个表呢?
us_order 表中的下单时间,推测 是凌晨,早上,上午,中午,下午,晚上。
在哪里下单在哪些表中出现?
us_order 、 user 、 user_addr
三个表是如何关联的?
us_order 有 user_id , user_addr 也有 user_id.
整体的一个做法:
1、将mysql中的数据,拉去到hive表中的ods层。(ods层就是原始数据层,最接近原始数据的层级)
2、dim层
用户信息表 , 用户的地址表
3、dw层
制作一个订单主题的宽表(将几个表中的字段都放在一个表中,字段很多)
4、dm层
统计出来的各种指标(数据集市)
5、将dm层的数据导出到mysql中即可。

三、实战

以上分析出各种层级,落地就是数据库(Hive中创建)。

创建四个数据库:

  1. create database ods_el;
  2. create database dim_el;
  3. create database dw_el;
  4. create database dm_el;

接着创建ods层中的表:us_order , order_delivery

在ods_el数据库中,常见us_order
image.png

  1. CREATE TABLE `us_order` (
  2. `order_id` bigint,
  3. `order_no` string,
  4. `order_date` string,
  5. `user_id` bigint,
  6. `user_name` string,
  7. `order_money` double,
  8. `order_type` int ,
  9. `order_status` int ,
  10. `pay_status` int,
  11. `pay_type` int ,
  12. `order_source` string,
  13. `update_time` string
  14. )
  15. partitioned by (dt string)
  16. row format delimited
  17. fields terminated by ','
  18. lines terminated by '\n'
  19. stored as textfile
  20. ;
  1. CREATE TABLE if not exists ods_el.order_delivery (
  2. `order_id` bigint,
  3. `order_no` string,
  4. `consignee` string,
  5. `area_id` bigint,
  6. `area_name` string,
  7. `address` string,
  8. `mobile` bigint,
  9. `phone` string,
  10. `coupon_id` bigint,
  11. `coupon_money` double,
  12. `carriage_money` double,
  13. `create_time` string,
  14. `update_time` string,
  15. `addr_id` bigint
  16. )
  17. partitioned by(dt string)
  18. row format delimited
  19. fields terminated by ','
  20. lines terminated by '\n'
  21. stored as textfile;

在维度层中创建 user 相关的表user, user_addr :

use dim_el;

  1. CREATE TABLE if not exists dim_el.`user` (
  2. `user_id` bigint,
  3. `user_name` string,
  4. `user_gender` tinyint,
  5. `user_birthday` string,
  6. `user_age` int,
  7. `constellation` string,
  8. `province` string,
  9. `city` string,
  10. `city_level` tinyint,
  11. `e_mail` string,
  12. `op_mail` string,
  13. `mobile` bigint,
  14. `num_seg_mobile` int,
  15. `op_Mobile` string,
  16. `register_time` string,
  17. `login_ip` string,
  18. `login_source` string,
  19. `request_user` string,
  20. `total_score` double,
  21. `used_score` double,
  22. `is_blacklist` tinyint,
  23. `is_married` tinyint,
  24. `education` string,
  25. `monthly_income` double,
  26. `profession` string,
  27. `create_date` string
  28. )row format delimited
  29. fields terminated by ','
  30. lines terminated by '\n'
  31. stored as textfile;
  1. CREATE TABLE if not exists dim_el.user_addr (
  2. `user_id` bigint,
  3. `order_addr` string,
  4. `user_order_flag` tinyint,
  5. `addr_id` bigint,
  6. `arear_id` int
  7. )
  8. row format delimited
  9. fields terminated by ','
  10. lines terminated by '\n'
  11. stored as textfile;

通过Sqoop工具,将mysql中的数据导入到hive中。

普通表:
新建hive表,会在hdfs上,生成一个文件地址,我向这个地址传递文件,hive表中就会有数据了。

  1. 通过表名的方式导入数据:
  2. sqoop import --connect jdbc:mysql://bigdata01:3306/qf_el \
  3. --username root --password 123456 \
  4. --table user \
  5. --target-dir /user/hive/warehouse/dim_el.db/user \
  6. --delete-target-dir \
  7. -m 1

导入数据后,查询一下。有数据:

  1. select * from `user` limit 10;

导入数据到hive表中,可以使用另一种形式:

  1. sqoop import --connect jdbc:mysql://192.168.32.100:3306/qf_el \
  2. --username root \
  3. --password 123456 \
  4. --table user \
  5. --hive-import \
  6. --hive-overwrite \
  7. --hive-table "user" \
  8. --hive-database dim_el \
  9. -m 1

继续导入user_addr表:
如果之前建好了表,也可以执行如下的命令:

  1. sqoop import \
  2. --connect jdbc:mysql://bigdata01:3306/qf_el \
  3. --username root \
  4. --password 123456 \
  5. --query "SELECT * FROM qf_el.user_addr where 1=1 and \$CONDITIONS" \
  6. --fields-terminated-by ',' \
  7. --target-dir /user/hive/warehouse/dim_el.db/user_addr \
  8. --delete-target-dir \
  9. --m 1

如果之前没有创建user_addr这个表的话:可以使用mySQL 导入 hive的方法:

  1. sqoop import --connect jdbc:mysql://192.168.32.100:3306/qf_el \
  2. --username root \
  3. --password 123456 \
  4. --table user_addr \
  5. --hive-import \
  6. --hive-overwrite \
  7. --hive-table "user_addr" \
  8. --hive-database dim_el \
  9. -m 1

如果之前已经创建了表结构,没有删除,那么执行以上命令不会报错,但是查询出来的结果为null。
如果碰到一下问题的解决办法:
image.png
在jdk路径下 jre/lib/security/java.policy ,添加:

  1. permission javax.management.MBeanTrustPermission "register";

image.png
切换ods_el,导入us_order 以及 order_delivery 这两个表的数据:

  1. sqoop import \
  2. --connect jdbc:mysql://bigdata01:3306/qf_el \
  3. --username root \
  4. --password 123456 \
  5. --query "SELECT * FROM qf_el.us_order uo WHERE DATE(uo.order_date) =
  6. '2022-04-21' and \$CONDITIONS" \
  7. --fields-terminated-by ',' \
  8. --target-dir /user/hive/warehouse/ods_el.db/us_order/dt=2022-04-21 \
  9. --delete-target-dir \
  10. -m 1

查询发现没有数据,需要给us_order 表添加分区:

  1. alter table us_order add partition(dt='2022-04-21');

如果你想分享三天的数据,需要导入其他两天的数据。

  1. update order_delivery
  2. set create_time='2022-04-21 11:59:59';

因为我们的us_order 中的数据是4月21日的数据,但是order_delivery 中,没有对应的日期,所以修改一下,让其有对应的数据。
抽取order_delivery 中的数据到 hive中

  1. sqoop import \
  2. --connect jdbc:mysql://bigdata01:3306/qf_el \
  3. --username root \
  4. --password 123456 \
  5. --query "SELECT * FROM qf_el.order_delivery uo WHERE DATE(uo.create_time) =
  6. '2022-04-21' and \$CONDITIONS" \
  7. --fields-terminated-by ',' \
  8. --target-dir /user/hive/warehouse/ods_el.db/order_delivery/dt=2022-04-21 \
  9. --delete-target-dir \
  10. -m 1
  1. alter table order_delivery add partition(dt='2022-04-21');

编写DW层:

在 dw_el 数据库中。
创建一个关于order订单的宽表。
创建这个表:
这个表中的字段一定要跟我们分析的指标靠近,略有富裕。

  1. create table order_wide_detail(
  2. `order_id` bigint ,
  3. `order_no` string,
  4. `order_date` string,
  5. `user_id` bigint ,
  6. `user_name` string,
  7. `order_money` double,
  8. `order_type` int ,
  9. `order_status` int ,
  10. `pay_status` int ,
  11. `pay_type` int ,
  12. `order_source` string,
  13. `update_time` string,
  14. `user_gender` tinyint,
  15. `user_birthday` string,
  16. `user_age` int ,
  17. `constellation` string,
  18. `province` string,
  19. `city` string,
  20. `city_level` tinyint ,
  21. `user_order_flag` tinyint
  22. )
  23. partitioned by(dt string)
  24. row format delimited
  25. fields terminated by ',';

向表中插入数据:

select * from 
   ods_el.us_order uo
   left join ods_el.order_delivery od
   on uo.order_no = od.order_no
   left join dim_el.user_addr ua
   on od.addr_id = ua.addr_id
   left join dim_el.`user` uu
   on uo.user_id = uu.user_id
   where uo.dt='2022-04-21';

将查询的数据导入到宽表中:

insert into order_wide_detail partition(dt='2022-04-21')
select 
uo.`order_id`  ,
  uo.`order_no` ,
  uo.`order_date` ,
  uo.`user_id`  ,
  uo.`user_name` ,
  uo.`order_money` ,
  uo.`order_type`  ,
  uo.`order_status`  ,
  uo.`pay_status`  ,
  uo.`pay_type`  ,
  uo.`order_source` ,
  uo.`update_time` ,
  uu.`user_gender` ,
  uu.`user_birthday` ,
  uu.`user_age`  ,
  uu.`constellation` ,
  uu.`province` ,
  uu.`city` ,
  uu.`city_level`  ,
  ua.`user_order_flag` 
from 
ods_el.us_order uo
   left join ods_el.order_delivery od
   on uo.order_no = od.order_no
   left join dim_el.user_addr ua
   on od.addr_id = ua.addr_id
   left join dim_el.`user` uu
   on uo.user_id = uu.user_id
   where uo.dt='2022-04-21';

宽表中有数据了,这个表就是我们进行分析的依据。

DM层—数据集市—就是各种统计的指标

1、统计2022-04-21 当天,在学校,公司,以及家里的下单量,以及凌晨,上午,中午,下午,晚上的下单量。
创建一个外部表:

create external table order_hour_locat_dist(
   `date` string,
   school_orders int,
   company_orders int,
   home_orders int,
   orders_0_5 int,
   orders_6_12 int,
   orders_13_15 int,
   orders_16_20 int,
   orders_21_24 int
)
partitioned by(dt string)
row format delimited fields terminated by ',';

分析数据:

insert into dm_el.order_hour_locat_dist partition(dt='2022-04-21')
select 
 to_date(order_date) `date`,
 sum(case when user_order_flag=1 then 1 else 0 end) school_orders,
 sum(case when user_order_flag=2 then 1 else 0 end) company_orders,
 sum(case when user_order_flag=3 then 1 else 0 end) home_orders,
 sum(case when hour(order_date) between 0 and 5 then 1 else 0 end) orders_0_5,
 sum(case when hour(order_date) between 6 and 12 then 1 else 0 end) orders_6_12,
 sum(case when hour(order_date) between 13 and 15 then 1 else 0 end) orders_13_15,
 sum(case when hour(order_date) between 16 and 20 then 1 else 0 end) orders_16_20,
 sum(case when hour(order_date) between 21 and 23 then 1 else 0 end) orders_21_24

from 
dw_el.order_wide_detail owd
where to_date(order_date) = '2022-04-21'
group by to_date(order_date);

查询表结果:

select * from order_hour_locat_dist;

image.png

分析结果导出:

在mysql中创建一个表,用于接收导出的数据:

CREATE TABLE `order_hour_location_dist` (
  `date` varchar(255) DEFAULT NULL,
  `school_orders` int DEFAULT NULL,
  `company_orders` int DEFAULT NULL,
  `home_orders` int DEFAULT NULL,
  `orders_0_5` int DEFAULT NULL,
  `orders_6_12` int DEFAULT NULL,
  `orders_13_15` int DEFAULT NULL,
  `orders_16_20` int DEFAULT NULL,
  `orders_21_24` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

使用sqoop导出结果:

sqoop export \
--connect jdbc:mysql://bigdata01:3306/el_report \
--username root \
--password 123456 \
--table order_hour_location_dist \
--fields-terminated-by ',' \
--export-dir /user/hive/warehouse/dm_el.db/order_hour_locat_dist/dt=2022-04-21 \
-m 1

image.png