SKU=Stock Keeping Unit(库存量单位)。即库存进出计量的基本单元,可以是以件,盒,托盘等为单位。SKU这是对于大型连锁超市DC(配送中心)物流管理的一个必要的方法。现在已经被引申为产品统一编号的简称,每种产品均对应有唯一的SKU号。
SPU(Standard Product Unit):标准化产品单元。是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。
首先通过检索搜索出来的商品列表中,每个商品都是一个SKU。每个SKU都有自己独立的库存数。也就是说每一个商品详情展示都是一个SKU。
比如,咱们购买一台iPhoneX手机,iPhoneX手机就是一个SPU,但是你购买的时候,不可能是以iPhoneX手机为单位买的,商家也不可能以iPhoneX为单位记录库存。必须要以什么颜色什么版本的iPhoneX为单位。比如,你购买的是一台银色、128G内存的、支持联通网络的iPhoneX ,商家也会以这个单位来记录库存数。那这个更细致的单位就叫库存单元(SKU)。
那spu又是干什么的呢?
如上图,一般的电商系统你点击进去以后,都能看到这个商品关联了其他好几个类似的商品,而且这些商品很多的信息都是共用的,比如商品图片,海报、销售属性等。
标签 |
含义 |
|
id |
订单编号 |
|
total_amount |
订单金额 |
|
order_status |
订单状态 |
|
user_id |
用户id |
|
payment_way |
支付方式 |
|
out_trade_no |
支付流水号 |
|
create_time |
创建时间 |
|
operate_time |
操作时间 |
标签 |
含义 |
|
id |
订单编号 |
|
order_id |
订单号 |
|
user_id |
用户id |
|
sku_id |
商品id |
|
sku_name |
商品名称 |
|
order_price |
下单价格 |
|
sku_num |
商品数量 |
|
create_time |
创建时间 |
标签 |
含义 |
|
id |
skuId |
|
spu_id |
spuid |
|
price |
价格 |
|
sku_name |
商品名称 |
|
sku_desc |
商品描述 |
|
weight |
重量 |
|
tm_id |
品牌id |
|
category3_id |
品类id |
|
create_time |
创建时间 |
标签 |
含义 |
|
id |
用户id |
|
name |
姓名 |
|
birthday |
生日 |
|
gender |
性别 |
|
|
邮箱 |
|
user_level |
用户等级 |
|
create_time |
创建时间 |
标签 |
含义 |
|
id |
id |
|
name |
名称 |
标签 |
含义 |
|
id |
id |
|
name |
名称 |
|
category1_id |
一级品类id |
标签 |
含义 |
|
id |
id |
|
name |
名称 |
|
Category2_id |
二级品类id |
标签 |
含义 |
|
id |
编号 |
|
out_trade_no |
对外业务编号 |
|
order_id |
订单编号 |
|
user_id |
用户编号 |
|
alipay_trade_no |
支付宝交易流水编号 |
|
total_amount |
支付金额 |
|
subject |
交易内容 |
|
payment_type |
支付类型 |
|
payment_time |
支付时间 |
实体表,一般是指一个现实存在的业务对象,比如用户,商品,商家,销售员等等。
用户表:
用户id |
姓名 |
生日 |
性别 |
邮箱 |
用户等级 |
创建时间 |
1 |
张三 |
2011-11-11 |
男 |
2 |
2018-11-11 |
|
2 |
李四 |
2011-11-11 |
女 |
3 |
2018-11-11 |
|
3 |
王五 |
2011-11-11 |
中性 |
1 |
2018-11-11 |
|
… |
… |
… |
… |
… |
… |
… |
维度表,一般是指对应一些业务状态,代码的解释表。也可以称之为码表。
比如地区表,订单状态,支付方式,审批状态,商品分类等等。
订单状态表:
订单状态编号 |
订单状态名称 |
1 |
未支付 |
2 |
支付 |
3 |
发货中 |
4 |
已发货 |
5 |
已完成 |
商品分类表:
商品分类编号 |
分类名称 |
1 |
少儿 |
2 |
文艺 |
3 |
生活 |
4 |
科技 |
事务型事实表,一般指随着业务发生不断产生的数据。特点是一旦发生不会再变化。
一般比如,交易流水,操作日志,出库入库记录等等。
交易流水表:
编号 |
对外业务编号 |
订单编号 |
用户编号 |
支付宝交易流水编号 |
支付金额 |
交易内容 |
支付类型 |
支付时间 |
1 |
7577697945 |
1 |
111 |
QEyF-63000323 |
223.00 |
海狗人参丸1 |
alipay |
2019-02-10 00:50:02 |
2 |
0170099522 |
2 |
222 |
qdwV-25111279 |
589.00 |
海狗人参丸2 |
wechatpay |
2019-02-10 00:50:02 |
3 |
1840931679 |
3 |
666 |
hSUS-65716585 |
485.00 |
海狗人参丸3 |
unionpay |
2019-02-10 00:50:02 |
。。。 |
。。。 |
。。。 |
。。。 |
。。。 |
。。。 |
。。。 |
。。。 |
。。。 |
周期型事实表,一般指随着业务发生不断产生的数据。
与事务型不同的是,数据会随着业务周期性的推进而变化。
比如订单,其中订单状态会周期性变化。再比如,请假、贷款申请,随着批复状态在周期性变化。
订单表:
订单编号 |
订单金额 |
订单状态 |
用户id |
支付方式 |
支付流水号 |
创建时间 |
操作时间 |
1 |
223.00 |
2 |
111 |
alipay |
QEyF-63000323 |
2019-02-10 00:01:29 |
2019-02-10 00:01:29 |
2 |
589.00 |
2 |
222 |
wechatpay |
qdwV-25111279 |
2019-02-10 00:05:02 |
2019-02-10 00:05:02 |
3 |
485.00 |
1 |
666 |
unionpay |
hSUS-65716585 |
2019-02-10 00:50:02 |
2019-02-10 00:50:02 |
。。。 |
。。。 |
。。。 |
。。。 |
。。。 |
。。。 |
。。。 |
。。。 |
数据同步策略的类型包括:全量表、增量表、新增及变化表、拉链表
全量表:存储完整的数据。
增量表:存储新增加的数据。
新增及变化表:存储新增加的数据和变化的数据。
拉链表:对新增及变化表做定期合并。
实体表:比如用户,商品,商家,销售员等
实体表数据量比较小:通常可以做每日全量,就是每天存一份完整数据。即每日全量。
维度表:比如订单状态,审批状态,商品分类
维度表数据量比较小:通常可以做每日全量,就是每天存一份完整数据。即每日全量。
说明:
1)针对可能会有变化的状态数据可以存储每日全量。
2)没变化的客观世界的维度(比如性别,地区,民族,政治成分,鞋子尺码)可以就存一份固定值。
事务型事实表:比如,交易流水,操作日志,出库入库记录等。
因为数据不会变化,而且数据量巨大,所以每天只同步新增数据即可,所以可以做成每日增量表,即每日创建一个分区存储。
周期型事实表:比如,订单、请假、贷款申请等
这类表从数据量的角度,存每日全量的话,数据量太大,冗余也太大。如果用每日增量的话无法反应数据变化。
每日新增及变化量可以用,包括了当日的新增和修改。一般来说这个表,足够计算大部分当日数据的。但是这种依然无法解决能够得到某一个历史时间点(时间切片)的切片数据。
所以要用利用每日新增和变化表,制作一张拉链表,以方便的取到某个时间切片的快照数据。所以我们需要得到每日新增及变化量。
拉链表:
name姓名 |
start新名字创建时间 |
end名字更改时间 |
张三 |
1990/1/1 |
2018/12/31 |
张三三 |
2019/1/1 |
9999-99-99 |
。。。 |
。。。 |
。。。 |
select * from user where start =<’2020-1-1’ and end>=’2020-1-1’
关系型数据库设计时,遵照一定的规范要求,目的在于降低数据的冗余性,目前业界范式有:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)、第五范式(5NF)。
范式的标准定义是:符合某一种级别的关系模式的集合,表示一个关系内部各属性之间的联系的合理化程度。通俗地讲,范式可以理解为一张数据表的表结构,所符合的某种设计标准的级别。
使用范式的根本目的是:
1)减少数据冗余,尽量让每个数据只出现一次。
2)保证数据一致性
缺点是获取数据时,需要通过join拼接出最后的数据。
关系模型主要应用与OLTP系统中,为了保证数据的一致性以及避免冗余,所以大部分业务系统的表都是遵循第三范式的。
维度模型主要应用于OLAP系统中,因为关系模型虽然冗余少,但是在大规模数据,跨表分析统计查询过程中,会造成多表关联,这会大大降低执行效率。
所以把相关各种表整理成两种:事实表和维度表两种。所有维度表围绕着事实表进行解释。
在维度建模的基础上又分为三种模型:星型模型、雪花模型、星座模型。
1)通过SQLyog创建数据库gmall
2)设置数据库编码
3)导入建表语句(1建表脚本)
选择->1建表脚本.sql
CREATE TABLE `order_info` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`consignee` VARCHAR(100) DEFAULT NULL COMMENT '收货人',
`consignee_tel` VARCHAR(20) DEFAULT NULL COMMENT '收件人电话',
`total_amount` DECIMAL(10,2) DEFAULT NULL COMMENT '总金额',
`order_status` VARCHAR(20) DEFAULT NULL COMMENT '订单状态',
`user_id` BIGINT(20) DEFAULT NULL COMMENT '用户id',
`payment_way` VARCHAR(20) DEFAULT NULL COMMENT '付款方式',
`delivery_address` VARCHAR(1000) DEFAULT NULL COMMENT '送货地址',
`order_comment` VARCHAR(200) DEFAULT NULL COMMENT '订单备注',
`out_trade_no` VARCHAR(50) DEFAULT NULL COMMENT '订单交易编号(第三方支付用)',
`trade_body` VARCHAR(200) DEFAULT NULL COMMENT '订单描述(第三方支付用)',
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
`operate_time` DATETIME DEFAULT NULL COMMENT '操作时间',
`expire_time` DATETIME DEFAULT NULL COMMENT '失效时间',
`tracking_no` VARCHAR(100) DEFAULT NULL COMMENT '物流单编号',
`parent_order_id` BIGINT(20) DEFAULT NULL COMMENT '父订单编号',
`img_url` VARCHAR(200) DEFAULT NULL COMMENT '图片路径',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='订单表 订单表';
DROP TABLE IF EXISTS sku_info;
CREATE TABLE `sku_info` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '库存id(itemID)',
`spu_id` BIGINT(20) DEFAULT NULL COMMENT '商品id',
`price` DECIMAL(10,0) DEFAULT NULL COMMENT '价格',
`sku_name` VARCHAR(200) DEFAULT NULL COMMENT 'sku名称',
`sku_desc` VARCHAR(2000) DEFAULT NULL COMMENT '商品规格描述',
`weight` DECIMAL(10,2) DEFAULT NULL COMMENT '重量',
`tm_id` BIGINT(20) DEFAULT NULL COMMENT '品牌(冗余)',
`category3_id` BIGINT(20) DEFAULT NULL COMMENT '三级分类id(冗余)',
`sku_default_img` VARCHAR(200) DEFAULT NULL COMMENT '默认显示图片(冗余)',
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8 COMMENT='库存单元表';
CREATE TABLE `user_info` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`login_name` VARCHAR(200) DEFAULT NULL COMMENT '用户名称',
`nick_name` VARCHAR(200) DEFAULT NULL COMMENT '用户昵称',
`passwd` VARCHAR(200) DEFAULT NULL COMMENT '用户密码',
`name` VARCHAR(200) DEFAULT NULL COMMENT '用户姓名',
`phone_num` VARCHAR(200) DEFAULT NULL COMMENT '手机号',
`email` VARCHAR(200) DEFAULT NULL COMMENT '邮箱',
`head_img` VARCHAR(200) DEFAULT NULL COMMENT '头像',
`user_level` VARCHAR(200) DEFAULT NULL COMMENT '用户级别',
`birthday` DATE DEFAULT NULL COMMENT '用户生日',
`gender` VARCHAR(1) DEFAULT NULL COMMENT '性别 M男,F女',
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=9501 DEFAULT CHARSET=utf8 COMMENT='用户表';
CREATE TABLE `order_detail` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`order_id` BIGINT(20) DEFAULT NULL COMMENT '订单编号',
`sku_id` BIGINT(20) DEFAULT NULL COMMENT 'sku_id',
`sku_name` VARCHAR(200) DEFAULT NULL COMMENT 'sku名称(冗余)',
`img_url` VARCHAR(200) DEFAULT NULL COMMENT '图片名称(冗余)',
`order_price` DECIMAL(10,2) DEFAULT NULL COMMENT '购买价格(下单时sku价格)',
`sku_num` VARCHAR(200) DEFAULT NULL COMMENT '购买个数',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=55750 DEFAULT CHARSET=utf8 COMMENT='订单明细表';
DROP TABLE IF EXISTS `payment_info`;
CREATE TABLE `payment_info`
(
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '编号',
`out_trade_no` VARCHAR(20) COMMENT '对外业务编号',
`order_id` VARCHAR(20) COMMENT '订单编号',
`user_id` VARCHAR(20) COMMENT '用户编号',
`alipay_trade_no` VARCHAR(20) COMMENT '支付宝交易流水编号',
`total_amount` DECIMAL(16,2) COMMENT '支付金额',
`subject` VARCHAR(20) COMMENT '交易内容',
`payment_type` VARCHAR(20) COMMENT '支付方式',
`payment_time` VARCHAR(20) COMMENT '支付时间',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=55750 DEFAULT CHARSET=utf8 COMMENT='支付流水表';
CREATE TABLE `base_category1`
(
`id` BIGINT AUTO_INCREMENT PRIMARY KEY NOT NULL COMMENT '编号',
`name` VARCHAR(10) NOT NULL COMMENT '分类名称'
);
ALTER TABLE `base_category1` COMMENT= '一级分类表';
CREATE TABLE `base_category2`
(
`id` BIGINT AUTO_INCREMENT PRIMARY KEY NOT NULL COMMENT '编号',
`name` VARCHAR(200) NOT NULL COMMENT '二级分类名称',
`category1_id` BIGINT COMMENT '一级分类编号'
);
ALTER TABLE `base_category2` COMMENT= '二级分类表';
CREATE TABLE `base_category3`
(
`id` BIGINT AUTO_INCREMENT PRIMARY KEY NOT NULL COMMENT '编号',
`name` VARCHAR(200) NOT NULL COMMENT '三级分类名称',
`category2_id` BIGINT COMMENT '二级分类编号'
);
ALTER TABLE `base_category3` COMMENT= '三级分类表';
#####
4)重复步骤3的导入方式,依次导入:2商品分类数据插入脚本、3函数脚本、4存储过程脚本。
1)生成业务数据函数说明
init_data ( do_date_string VARCHAR(20) , order_incr_num INT, user_incr_num INT , sku_num INT , if_truncate BOOLEAN ):
参数一:do_date_string生成数据日期
参数二:order_incr_num订单id个数
参数三:user_incr_num用户id个数
参数四:sku_num商品sku个数
参数五:if_truncate是否参数数据
2)案例测试:
(1)需求:生成日期2019年2月10日数据、订单1000个、用户200个、商品sku300个、不删除数据。
DELIMITER $$
DROP PROCEDURE IF EXISTS `insert_sku`$$
##新增max_num个sku
CREATE DEFINER=`root`@`localhost` PROCEDURE `insert_sku`( create_time_string VARCHAR(200),max_num INT )
BEGIN
DECLARE v_create_time DATETIME DEFAULT NULL;
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i + 1;
SET v_create_time=DATE_ADD(DATE_FORMAT(create_time_string,'%Y-%m-%d') ,INTERVAL rand_num(1,3600*24) SECOND);
INSERT INTO sku_info (spu_id,price,sku_name,sku_desc,weight,tm_id,category3_id,sku_default_img,create_time )
VALUES (rand_num(1,1000) ,rand_num(10,5000) , rand_string(20), rand_string(30),CAST(rand_num(50,500) AS DECIMAL(10,2))/100.0 ,rand_num(1,100), rand_num(1,5000),CONCAT('http://',rand_string(40)), v_create_time );
UNTIL i = max_num
END REPEAT;
COMMIT;
END$$
DELIMITER ;
DELIMITER $$
DROP PROCEDURE IF EXISTS `insert_user`$$
#随机产生max_num个用户
CREATE DEFINER=`root`@`localhost` PROCEDURE `insert_user`( create_time_string VARCHAR(200),max_num INT )
BEGIN
DECLARE v_create_time DATETIME DEFAULT NULL;
DECLARE i INT DEFAULT 0;
DECLARE v_birthday DATE DEFAULT 0;
DECLARE v_gender VARCHAR(1) DEFAULT NULL;
SET autocommit = 0;
REPEAT
SET i = i + 1;
SET v_create_time=DATE_ADD(DATE_FORMAT(create_time_string,'%Y-%m-%d') ,INTERVAL rand_num(1,3600*24) SECOND);
SET v_birthday=DATE_ADD(DATE_FORMAT('1950-01-01','%Y-%m-%d') ,INTERVAL rand_num(1,365*50) DAY);
SET v_gender=IF(rand_num(0,1)=0,'M','F');
INSERT INTO user_info (login_name,nick_name,passwd,NAME,phone_num,email,head_img,user_level,birthday,gender,create_time )
VALUES (rand_string(20) ,rand_string(20) , CONCAT('pwd',rand_string(20)), rand_string(30), CONCAT('13',rand_nums(0,9,9,'')) ,CONCAT(rand_string(8),'@',rand_string(3),'.com') , CONCAT('http://',rand_string(40)), rand_num(1,5),v_birthday,v_gender,v_create_time );
UNTIL i = max_num
END REPEAT;
COMMIT;
END$$
DELIMITER ;
DELIMITER $$
DROP PROCEDURE IF EXISTS `insert_order`$$
##生成订单
CREATE DEFINER=`root`@`localhost` PROCEDURE `insert_order`( create_time_string VARCHAR(200),max_num INT,user_num INT ,sku_num INT )
BEGIN
DECLARE v_create_time DATETIME DEFAULT NULL;
DECLARE i INT DEFAULT 0;
DECLARE v_order_status INT DEFAULT 0;
DECLARE v_operate_time DATETIME DEFAULT NULL;
DECLARE v_order_id INT DEFAULT NULL;
DECLARE v_order_detail_num INT DEFAULT NULL;
DECLARE j INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i + 1;
SET v_create_time=DATE_ADD(DATE_FORMAT(create_time_string,'%Y-%m-%d') ,INTERVAL rand_num(30,3600*23) SECOND);
SET v_order_status=rand_num(1,2); ##
IF v_order_status>1 THEN
SET v_operate_time= DATE_ADD(v_create_time ,INTERVAL rand_num(30,3600) SECOND);
ELSE
SET v_operate_time=NULL ;
END IF ;
INSERT INTO order_info (consignee, consignee_tel,total_amount ,order_status ,user_id,payment_way,delivery_address,order_comment,out_trade_no,trade_body,create_time,operate_time,expire_time, tracking_no,parent_order_id ,img_url)
VALUES (rand_string(6) , CONCAT('13',rand_nums(0,9,9,'')),CAST(rand_num(50,1000) AS DECIMAL(10,2)) ,v_order_status ,rand_num(1,user_num), rand_num(1,2),rand_string(20),rand_string(20),rand_nums(0,9,10,''),'',v_create_time, v_operate_time,NULL,NULL,NULL,NULL );
SELECT LAST_INSERT_ID() INTO v_order_id ;
SET v_order_detail_num=rand_num(1,5);
WHILE j0 , DATE_ADD(v_operate_time ,INTERVAL rand_num(30,20*3600) SECOND),operate_time)
WHERE o.`order_status`<5;
END$$
DELIMITER ;
DELIMITER$$
DROP PROCEDURE IF EXISTS `insert_payment`$$
## 只要订单状态更新为2 ,给当天插入一条支付信息
CREATE DEFINER=`root`@`localhost` PROCEDURE `insert_payment`( do_date_str VARCHAR(200) )
BEGIN
INSERT INTO payment_info (out_trade_no,order_id,user_id,alipay_trade_no,total_amount,`subject`,payment_type,payment_time )
SELECT o.out_trade_no,o.id,user_id,
CONCAT( rand_string(4),'-',rand_nums(0,9,8,'')) alipay_trade_no,
o.total_amount,
rand_string(8) `subject`,
( CASE rand_num(1,3) WHEN 1 THEN 'wechatpay' WHEN 2 THEN 'alipay' WHEN 3 THEN 'unionpay' END) payment_type ,
IF(o.operate_time IS NULL,o.create_time,o.operate_time) payment_time
FROM order_info o
WHERE (DATE_FORMAT(o.create_time,'%Y-%m-%d')= do_date_str OR DATE_FORMAT(o.operate_time,'%Y-%m-%d')= do_date_str ) AND o.order_status='2';
COMMIT;
END$$
DELIMITER ;
DELIMITER $$
DROP PROCEDURE IF EXISTS `init_data`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `init_data`( do_date_string VARCHAR(20) ,order_incr_num INT,user_incr_num INT ,sku_num INT ,if_truncate BOOLEAN )
BEGIN
DECLARE user_count INT DEFAULT 0;
DECLARE sku_count INT DEFAULT 0;
DECLARE do_date VARCHAR(20) DEFAULT do_date_string;
IF if_truncate THEN
TRUNCATE TABLE order_info ;
TRUNCATE TABLE order_detail ;
TRUNCATE TABLE sku_info ;
TRUNCATE TABLE user_info ;
END IF ;
CALL insert_sku(do_date,sku_num );
SELECT COUNT(*) INTO sku_count FROM sku_info;
CALL insert_user(do_date,user_incr_num );
SELECT COUNT(*) INTO user_count FROM user_info;
CALL update_order(do_date);
CALL insert_order(do_date,order_incr_num,user_count,sku_count);
CALL insert_payment(do_date);
END$$
DELIMITER ;
CALL init_data('2019-02-10',1000,200,300,FALSE);
(2)查询生成数据结果
SELECT * from base_category1;
SELECT * from base_category2;
SELECT * FROM base_category3;
SELECT * FROM order_info;
SELECT * from order_detail;
SELECT * from sku_info;
SELECT * from user_info;
SELECT * FROM payment_info;
(3)生成2019年2月11日数据
CALL init_data('2019-02-11',1000,200,300,FALSE);
=================================== Begin ===========================
安装Sqoop的前提是已经具备Java和Hadoop的环境。
1) 下载地址:http://mirrors.hust.edu.cn/apache/sqoop/1.4.6/
2) 上传安装包sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz到虚拟机中
3) 解压sqoop安装包到指定目录,如:
$ tar -zxf sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz -C /opt/module/
Sqoop的配置文件与大多数大数据框架类似,在sqoop根目录下的conf目录中。
1) 重命名配置文件
$ mv sqoop-env-template.sh sqoop-env.sh
2) 修改配置文件
sqoop-env.sh
export HADOOP_COMMON_HOME=/opt/module/hadoop-2.7.2
export HADOOP_MAPRED_HOME=/opt/module/hadoop-2.7.2
export HIVE_HOME=/opt/module/hive
export ZOOKEEPER_HOME=/opt/module/zookeeper-3.4.10
export ZOOCFGDIR=/opt/module/zookeeper-3.4.10
export HBASE_HOME=/opt/module/hbase
拷贝jdbc驱动到sqoop的lib目录下,如:
$ cp mysql-connector-java-5.1.27-bin.jar /opt/module/sqoop-1.4.6.bin__hadoop-2.0.4-alpha/lib/
我们可以通过某一个command来验证sqoop配置是否正确:
$ bin/sqoop help
出现一些Warning警告(警告信息已省略),并伴随着帮助命令的输出:
Available commands:
codegen Generate code to interact with database records
create-hive-table Import a table definition into Hive
eval Evaluate a SQL statement and display the results
export Export an HDFS directory to a database table
help List available commands
import Import a table from a database to HDFS
import-all-tables Import tables from a database to HDFS
import-mainframe Import datasets from a mainframe server to HDFS
job Work with saved jobs
list-databases List available databases on a server
list-tables List available tables in a database
merge Merge results of incremental imports
metastore Run a standalone Sqoop metastore
version Display version information
$ bin/sqoop list-databases --connect jdbc:mysql://hadoop102:3306/ --username root --password 000000
出现如下输出:
information_schema
metastore
mysql
oozie
performance_schema
在Sqoop中,“导入”概念指:从非大数据集群(RDBMS)向大数据集群(HDFS,HIVE,HBASE)中传输数据,叫做:导入,即使用import关键字。
1) 确定Mysql服务开启正常
2) 在Mysql中新建一张表并插入一些数据
$ mysql -uroot -p000000
mysql> create database company;
mysql> create table company.staff(id int(4) primary key not null auto_increment, name varchar(255), sex varchar(255));
mysql> insert into company.staff(name, sex) values('Thomas', 'Male');
mysql> insert into company.staff(name, sex) values('Catalina', 'FeMale');
3) 导入数据
(1)全部导入
$ bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--table staff \
--target-dir /user/company \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t"
(2)查询导入
$ bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--target-dir /user/company \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t" \
--query 'select name,sex from staff where id <=1 and $CONDITIONS;'
提示:must contain '$CONDITIONS' in WHERE clause.
如果query后使用的是双引号,则$CONDITIONS前必须加转移符,防止shell识别为自己的变量。
(3)导入指定列
$ bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--target-dir /user/company \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t" \
--columns id,sex \
--table staff
提示:columns中如果涉及到多列,用逗号分隔,分隔时不要添加空格
(4)使用sqoop关键字筛选查询导入数据
$ bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--target-dir /user/company \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t" \
--table staff \
--where "id=1"
$ bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--table staff \
--num-mappers 1 \
--hive-import \
--fields-terminated-by "\t" \
--hive-overwrite \
--hive-table staff_hive
提示:该过程分为两步,第一步将数据导入到HDFS,第二步将导入到HDFS的数据迁移到Hive仓库,第一步默认的临时目录是/user/newbies/表名
$ bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--table company \
--columns "id,name,sex" \
--column-family "info" \
--hbase-create-table \
--hbase-row-key "id" \
--hbase-table "hbase_company" \
--num-mappers 1 \
--split-by id
提示:sqoop1.4.6只支持HBase1.0.1之前的版本的自动创建HBase表的功能
解决方案:手动创建HBase表
hbase> create 'hbase_company,'info'
(5) 在HBase中scan这张表得到如下内容
hbase> scan ‘hbase_company’
在Sqoop中,“导出”概念指:从大数据集群(HDFS,HIVE,HBASE)向非大数据集群(RDBMS)中传输数据,叫做:导出,即使用export关键字。
$ bin/sqoop export \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--table staff \
--num-mappers 1 \
--export-dir /user/hive/warehouse/staff_hive \
--input-fields-terminated-by "\t"
提示:Mysql中如果表不存在,不会自动创建
使用opt格式的文件打包sqoop命令,然后执行
1) 创建一个.opt文件
$ mkdir opt
$ touch opt/job_HDFS2RDBMS.opt
2) 编写sqoop脚本
$ vi opt/job_HDFS2RDBMS.opt
export
--connect
jdbc:mysql://hadoop102:3306/company
--username
root
--password
000000
--table
staff
--num-mappers
1
--export-dir
/user/hive/warehouse/staff_hive
--input-fields-terminated-by
"\t"
3) 执行该脚本
$ bin/sqoop --options-file opt/job_HDFS2RDBMS.opt
=========================== End ==============================================
/opt/module/sqoop/bin/sqoop import \
--connect \
--username \
--password \
--target-dir \
--delete-target-dir \
--num-mappers \
--fields-terminated-by \
--query "$2"' and $CONDITIONS;'
1)在/home/newbies/bin目录下创建脚本sqoop_import.sh
[newbies@hadoop102 bin]$ vim sqoop_import.sh
在脚本中填写如下内容
#!/bin/bash
db_date=$2
echo $db_date
db_name=gmall
import_data() {
/opt/module/sqoop/bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/$db_name \
--username root \
--password 000000 \
--target-dir /origin_data/$db_name/db/$1/$db_date \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t" \
--query "$2"' and $CONDITIONS;'
}
import_sku_info(){
import_data "sku_info" "select
id, spu_id, price, sku_name, sku_desc, weight, tm_id,
category3_id, create_time
from sku_info where 1=1"
}
import_user_info(){
import_data "user_info" "select
id, name, birthday, gender, email, user_level,
create_time
from user_info where 1=1"
}
import_base_category1(){
import_data "base_category1" "select
id, name from base_category1 where 1=1"
}
import_base_category2(){
import_data "base_category2" "select
id, name, category1_id from base_category2 where 1=1"
}
import_base_category3(){
import_data "base_category3" "select id, name, category2_id from base_category3 where 1=1"
}
import_order_detail(){
import_data "order_detail" "select
od.id,
order_id,
user_id,
sku_id,
sku_name,
order_price,
sku_num,
o.create_time
from order_info o , order_detail od
where o.id=od.order_id
and DATE_FORMAT(create_time,'%Y-%m-%d')='$db_date'"
}
import_payment_info(){
import_data "payment_info" "select
id,
out_trade_no,
order_id,
user_id,
alipay_trade_no,
total_amount,
subject ,
payment_type,
payment_time
from payment_info
where DATE_FORMAT(payment_time,'%Y-%m-%d')='$db_date'"
}
import_order_info(){
import_data "order_info" "select
id,
total_amount,
order_status,
user_id,
payment_way,
out_trade_no,
create_time,
operate_time
from order_info
where (DATE_FORMAT(create_time,'%Y-%m-%d')='$db_date' or DATE_FORMAT(operate_time,'%Y-%m-%d')='$db_date')"
}
case $1 in
"base_category1")
import_base_category1
;;
"base_category2")
import_base_category2
;;
"base_category3")
import_base_category3
;;
"order_info")
import_order_info
;;
"order_detail")
import_order_detail
;;
"sku_info")
import_sku_info
;;
"user_info")
import_user_info
;;
"payment_info")
import_payment_info
;;
"all")
import_base_category1
import_base_category2
import_base_category3
import_order_info
import_order_detail
import_sku_info
import_user_info
import_payment_info
;;
esac
2)增加脚本执行权限
[newbies@hadoop102 bin]$ chmod 777 sqoop_import.sh
3)执行脚本导入数据
[newbies@hadoop102 bin]$ sqoop_import.sh all 2019-02-10
[newbies@hadoop102 bin]$ sqoop_import.sh all 2019-02-11
完全仿照业务数据库中的表字段,一模一样的创建ODS层对应表。
hive (gmall)>
drop table if exists ods_order_info;
create table ods_order_info (
`id` string COMMENT '订单编号',
`total_amount` decimal(10,2) COMMENT '订单金额',
`order_status` string COMMENT '订单状态',
`user_id` string COMMENT '用户id' ,
`payment_way` string COMMENT '支付方式',
`out_trade_no` string COMMENT '支付流水号',
`create_time` string COMMENT '创建时间',
`operate_time` string COMMENT '操作时间'
) COMMENT '订单表'
PARTITIONED BY ( `dt` string)
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ods/ods_order_info/'
tblproperties ("parquet.compression"="snappy")
;
hive (gmall)>
drop table if exists ods_order_detail;
create table ods_order_detail(
`id` string COMMENT '订单编号',
`order_id` string COMMENT '订单号',
`user_id` string COMMENT '用户id' ,
`sku_id` string COMMENT '商品id',
`sku_name` string COMMENT '商品名称',
`order_price` string COMMENT '下单价格',
`sku_num` string COMMENT '商品数量',
`create_time` string COMMENT '创建时间'
) COMMENT '订单明细表'
PARTITIONED BY ( `dt` string)
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ods/ods_order_detail/'
tblproperties ("parquet.compression"="snappy")
;
3.3.3 创建商品表
hive (gmall)>
drop table if exists ods_sku_info;
create table ods_sku_info(
`id` string COMMENT 'skuId',
`spu_id` string COMMENT 'spuid',
`price` decimal(10,2) COMMENT '价格' ,
`sku_name` string COMMENT '商品名称',
`sku_desc` string COMMENT '商品描述',
`weight` string COMMENT '重量',
`tm_id` string COMMENT '品牌id',
`category3_id` string COMMENT '品类id',
`create_time` string COMMENT '创建时间'
) COMMENT '商品表'
PARTITIONED BY ( `dt` string)
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ods/ods_sku_info/'
tblproperties ("parquet.compression"="snappy")
;
hive (gmall)>
drop table if exists ods_user_info;
create table ods_user_info(
`id` string COMMENT '用户id',
`name` string COMMENT '姓名',
`birthday` string COMMENT '生日' ,
`gender` string COMMENT '性别',
`email` string COMMENT '邮箱',
`user_level` string COMMENT '用户等级',
`create_time` string COMMENT '创建时间'
) COMMENT '用户信息'
PARTITIONED BY ( `dt` string)
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ods/ods_user_info/'
tblproperties ("parquet.compression"="snappy")
;
hive (gmall)>
drop table if exists ods_base_category1;
create table ods_base_category1(
`id` string COMMENT 'id',
`name` string COMMENT '名称'
) COMMENT '商品一级分类'
PARTITIONED BY ( `dt` string)
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ods/ods_base_category1/'
tblproperties ("parquet.compression"="snappy")
;
hive (gmall)>
drop table if exists ods_base_category2;
create external table ods_base_category2(
`id` string COMMENT ' id',
`name` string COMMENT '名称',
category1_id string COMMENT '一级品类id'
) COMMENT '商品二级分类'
PARTITIONED BY ( `dt` string)
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ods/ods_base_category2/'
tblproperties ("parquet.compression"="snappy")
;
hive (gmall)>
drop table if exists ods_base_category3;
create table ods_base_category3(
`id` string COMMENT ' id',
`name` string COMMENT '名称',
category2_id string COMMENT '二级品类id'
) COMMENT '商品三级分类'
PARTITIONED BY ( `dt` string)
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ods/ods_base_category3/'
tblproperties ("parquet.compression"="snappy")
;
hive (gmall)>
drop table if exists `ods_payment_info`;
create table `ods_payment_info`(
`id` bigint COMMENT '编号',
`out_trade_no` string COMMENT '对外业务编号',
`order_id` string COMMENT '订单编号',
`user_id` string COMMENT '用户编号',
`alipay_trade_no` string COMMENT '支付宝交易流水编号',
`total_amount` decimal(16,2) COMMENT '支付金额',
`subject` string COMMENT '交易内容',
`payment_type` string COMMENT '支付类型',
`payment_time` string COMMENT '支付时间'
) COMMENT '支付流水表'
PARTITIONED BY ( `dt` string)
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ods/ods_payment_info/'
tblproperties ("parquet.compression"="snappy")
;
1)在/home/newbies/bin目录下创建脚本ods_db.sh
[newbies@hadoop102 bin]$ vim ods_db.sh
在脚本中填写如下内容
#!/bin/bash
do_date=$1
APP=gmall
hive=/opt/module/hive/bin/hive
sql="
load data inpath '/origin_data/$APP/db/order_info/$do_date' OVERWRITE into table $APP"".ods_order_info partition(dt='$do_date');
load data inpath '/origin_data/$APP/db/order_detail/$do_date' OVERWRITE into table $APP"".ods_order_detail partition(dt='$do_date');
load data inpath '/origin_data/$APP/db/sku_info/$do_date' OVERWRITE into table $APP"".ods_sku_info partition(dt='$do_date');
load data inpath '/origin_data/$APP/db/user_info/$do_date' OVERWRITE into table $APP"".ods_user_info partition(dt='$do_date');
load data inpath '/origin_data/$APP/db/payment_info/$do_date' OVERWRITE into table $APP"".ods_payment_info partition(dt='$do_date');
load data inpath '/origin_data/$APP/db/base_category1/$do_date' OVERWRITE into table $APP"".ods_base_category1 partition(dt='$do_date');
load data inpath '/origin_data/$APP/db/base_category2/$do_date' OVERWRITE into table $APP"".ods_base_category2 partition(dt='$do_date');
load data inpath '/origin_data/$APP/db/base_category3/$do_date' OVERWRITE into table $APP"".ods_base_category3 partition(dt='$do_date');
"
$hive -e "$sql"
2)增加脚本执行权限
[newbies@hadoop102 bin]$ chmod 777 ods_db.sh
3)执行脚本导入数据
[newbies@hadoop102 bin]$ ods_db.sh 2019-02-10
[newbies@hadoop102 bin]$ ods_db.sh 2019-02-11
4)查询导入数据
hive (gmall)>
select * from ods_order_info where dt='2019-02-10' limit 1;
select * from ods_order_info where dt='2019-02-11' limit 1;
积压ODS层对数据进行判空过滤。对商品分类表进行维度退化(降维)。
hive (gmall)>
drop table if exists dwd_order_info;
create external table dwd_order_info (
`id` string COMMENT '',
`total_amount` decimal(10,2) COMMENT '',
`order_status` string COMMENT ' 1 2 3 4 5',
`user_id` string COMMENT 'id' ,
`payment_way` string COMMENT '',
`out_trade_no` string COMMENT '',
`create_time` string COMMENT '',
`operate_time` string COMMENT ''
) COMMENT ''
PARTITIONED BY ( `dt` string)
stored as parquet
location '/warehouse/gmall/dwd/dwd_order_info/'
tblproperties ("parquet.compression"="snappy")
;
hive (gmall)>
drop table if exists dwd_order_detail;
create external table dwd_order_detail(
`id` string COMMENT '',
`order_id` decimal(10,2) COMMENT '',
`user_id` string COMMENT 'id' ,
`sku_id` string COMMENT 'id',
`sku_name` string COMMENT '',
`order_price` string COMMENT '',
`sku_num` string COMMENT '',
`create_time` string COMMENT ''
) COMMENT ''
PARTITIONED BY ( `dt` string)
stored as parquet
location '/warehouse/gmall/dwd/dwd_order_detail/'
tblproperties ("parquet.compression"="snappy")
;
hive (gmall)>
drop table if exists dwd_user_info;
create external table dwd_user_info(
`id` string COMMENT 'id',
`name` string COMMENT '',
`birthday` string COMMENT '' ,
`gender` string COMMENT '',
`email` string COMMENT '',
`user_level` string COMMENT '',
`create_time` string COMMENT ''
) COMMENT ''
PARTITIONED BY ( `dt` string)
stored as parquet
location '/warehouse/gmall/dwd/dwd_user_info/'
tblproperties ("parquet.compression"="snappy")
;
hive (gmall)>
drop table if exists `dwd_payment_info`;
create external table `dwd_payment_info`(
`id` bigint COMMENT '',
`out_trade_no` string COMMENT '',
`order_id` string COMMENT '',
`user_id` string COMMENT '',
`alipay_trade_no` string COMMENT '',
`total_amount` decimal(16,2) COMMENT '',
`subject` string COMMENT '',
`payment_type` string COMMENT '',
`payment_time` string COMMENT ''
) COMMENT ''
PARTITIONED BY ( `dt` string)
stored as parquet
location '/warehouse/gmall/dwd/dwd_payment_info/'
tblproperties ("parquet.compression"="snappy")
;
hive (gmall)>
drop table if exists dwd_sku_info;
create external table dwd_sku_info(
`id` string COMMENT 'skuId',
`spu_id` string COMMENT 'spuid',
`price` decimal(10,2) COMMENT '' ,
`sku_name` string COMMENT '',
`sku_desc` string COMMENT '',
`weight` string COMMENT '',
`tm_id` string COMMENT 'id',
`category3_id` string COMMENT '1id',
`category2_id` string COMMENT '2id',
`category1_id` string COMMENT '3id',
`category3_name` string COMMENT '3',
`category2_name` string COMMENT '2',
`category1_name` string COMMENT '1',
`create_time` string COMMENT ''
) COMMENT ''
PARTITIONED BY ( `dt` string)
stored as parquet
location '/warehouse/gmall/dwd/dwd_sku_info/'
tblproperties ("parquet.compression"="snappy")
;
1)在/home/newbies/bin目录下创建脚本dwd_db.sh
[newbies@hadoop102 bin]$ vim dwd_db.sh
在脚本中填写如下内容
#!/bin/bash
# 定义变量方便修改
APP=gmall
hive=/opt/module/hive/bin/hive
# 如果是输入的日期按照取输入日期;如果没输入日期取当前时间的前一天
if [ -n $1 ] ;then
log_date=$1
else
log_date=`date -d "-1 day" +%F`
fi
sql="
set hive.exec.dynamic.partition.mode=nonstrict;
insert overwrite table "$APP".dwd_order_info partition(dt)
select * from "$APP".ods_order_info
where dt='$log_date' and id is not null;
insert overwrite table "$APP".dwd_order_detail partition(dt)
select * from "$APP".ods_order_detail
where dt='$log_date' and id is not null;
insert overwrite table "$APP".dwd_user_info partition(dt)
select * from "$APP".ods_user_info
where dt='$log_date' and id is not null;
insert overwrite table "$APP".dwd_payment_info partition(dt)
select * from "$APP".ods_payment_info
where dt='$log_date' and id is not null;
insert overwrite table "$APP".dwd_sku_info partition(dt)
select
sku.id,
sku.spu_id,
sku.price,
sku.sku_name,
sku.sku_desc,
sku.weight,
sku.tm_id,
sku.category3_id,
c2.id category2_id ,
c1.id category1_id,
c3.name category3_name,
c2.name category2_name,
c1.name category1_name,
sku.create_time,
sku.dt
from
"$APP".ods_sku_info sku
join "$APP".ods_base_category3 c3 on sku.category3_id=c3.id
join "$APP".ods_base_category2 c2 on c3.category2_id=c2.id
join "$APP".ods_base_category1 c1 on c2.category1_id=c1.id
where sku.dt='$log_date' and c2.dt='$log_date'
and c3.dt='$log_date' and c1.dt='$log_date'
and sku.id is not null;
"
$hive -e "$sql"
2)增加脚本执行权限
[newbies@hadoop102 bin]$ chmod 777 dwd_db.sh
3)执行脚本导入数据
[newbies@hadoop102 bin]$ dwd_db.sh 2019-02-10
[newbies@hadoop102 bin]$ dwd_db.sh 2019-02-11
4)查看导入数据
hive (gmall)>
select * from dwd_sku_info where dt='2019-02-10' limit 2;
select * from dwd_sku_info where dt='2019-02-11' limit 2;
思考:
1)维度退化要付出什么代价?或者说会造成什么样的需求处理不了?
如果被退化的维度,还有其他业务表使用,退化后处理起来就麻烦些。
2)想想在实际业务中还有那些维度表可以退化
1)为什么要建宽表
需求目标,把每个用户单日的行为聚合起来组成一张多列宽表,以便之后关联用户维度信息后进行,不同角度的统计分析。
hive (gmall)>
drop table if exists dws_user_action;
create external table dws_user_action
(
user_id string comment '用户 id',
order_count bigint comment '下单次数 ',
order_amount decimal(16,2) comment '下单金额 ',
payment_count bigint comment '支付次数',
payment_amount decimal(16,2) comment '支付金额 ',
comment_count bigint comment '评论次数'
) COMMENT '每日用户行为宽表'
PARTITIONED BY ( `dt` string)
stored as parquet
location '/warehouse/gmall/dws/dws_user_action/'
tblproperties ("parquet.compression"="snappy");
1)导入数据
hive (gmall)>
with
tmp_order as
(
select
user_id,
sum(oc.total_amount) order_amount,
count(*) order_count
from dwd_order_info oc
where date_format(oc.create_time,'yyyy-MM-dd')='2019-02-10'
group by user_id
) ,
tmp_payment as
(
select
user_id,
sum(pi.total_amount) payment_amount,
count(*) payment_count
from dwd_payment_info pi
where date_format(pi.payment_time,'yyyy-MM-dd')='2019-02-10'
group by user_id
),
tmp_comment as
(
select
user_id,
count(*) comment_count
from dwd_comment_log c
where date_format(c.dt,'yyyy-MM-dd')='2019-02-10'
group by user_id
)
insert overwrite table dws_user_action partition(dt='2019-02-10')
select
user_actions.user_id,
sum(user_actions.order_count),
sum(user_actions.order_amount),
sum(user_actions.payment_count),
sum(user_actions.payment_amount),
sum(user_actions.comment_count)
from
(
select
user_id,
order_count,
order_amount ,
0 payment_count ,
0 payment_amount,
0 comment_count
from tmp_order
union all
select
user_id,
0,
0,
payment_count,
payment_amount,
0
from tmp_payment
union all
select
user_id,
0,
0,
0,
0,
comment_count
from tmp_comment
) user_actions
group by user_id;
2)查询导入结果
hive (gmall)> select * from dws_user_action ;
1)在/home/newbies/bin目录下创建脚本dws_db_wide.sh
[newbies@hadoop102 bin]$ vim dws_db_wide.sh
在脚本中填写如下内容
#!/bin/bash
# 定义变量方便修改
APP=gmall
hive=/opt/module/hive/bin/hive
# 如果是输入的日期按照取输入日期;如果没输入日期取当前时间的前一天
if [ -n $1 ] ;then
log_date=$1
else
log_date=`date -d "-1 day" +%F`
fi
sql="
with
tmp_order as
(
select
user_id,
sum(oc.total_amount) order_amount,
count(*) order_count
from "$APP".dwd_order_info oc
where date_format(oc.create_time,'yyyy-MM-dd')='$log_date'
group by user_id
) ,
tmp_payment as
(
select
user_id,
sum(pi.total_amount) payment_amount,
count(*) payment_count
from "$APP".dwd_payment_info pi
where date_format(pi.payment_time,'yyyy-MM-dd')='$log_date'
group by user_id
),
tmp_comment as
(
select
user_id,
count(*) comment_count
from "$APP".dwd_comment_log c
where date_format(c.dt,'yyyy-MM-dd')='$log_date'
group by user_id
)
insert overwrite table "$APP".dws_user_action partition(dt='$log_date')
select
user_actions.user_id,
sum(user_actions.order_count),
sum(user_actions.order_amount),
sum(user_actions.payment_count),
sum(user_actions.payment_amount),
sum(user_actions.comment_count)
from
(
select
user_id,
order_count,
order_amount ,
0 payment_count ,
0 payment_amount,
0 comment_count
from tmp_order
union all
select
user_id,
0,
0,
payment_count,
payment_amount,
0
from tmp_payment
union all
select
user_id,
0,
0,
0,
0,
comment_count
from tmp_comment
) user_actions
group by user_id;
"
$hive -e "$sql"
2)增加脚本执行权限
[newbies@hadoop102 bin]$ chmod 777 dws_db_wide.sh
3)执行脚本导入数据
[newbies@hadoop102 bin]$ dws_db_wide.sh 2019-02-11
4)查看导入数据
hive (gmall)>
select * from dws_user_action where dt='2019-02-11' limit 2;
hive (gmall)>
drop table if exists ads_gmv_sum_day;
create table ads_gmv_sum_day(
`dt` string COMMENT '统计日期',
`gmv_count` bigint COMMENT '当日gmv订单个数',
`gmv_amount` decimal(16,2) COMMENT '当日gmv订单总金额',
`gmv_payment` decimal(16,2) COMMENT '当日支付金额'
) COMMENT '每日活跃用户数量'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_gmv_sum_day/'
;
1)数据导入
hive (gmall)>
insert into table ads_gmv_sum_day
select
'2019-02-10' dt ,
sum(order_count) gmv_count ,
sum(order_amount) gmv_amount ,
sum(payment_amount) payment_amount
from dws_user_action
where dt ='2019-02-10'
group by dt
;
2)查询导入数据
hive (gmall)> select * from ads_gmv_sum_day;
hive (gmall)>
drop table if exists ads_user_convert_day;
create table ads_user_convert_day(
`dt` string COMMENT '统计日期',
`uv_m_count` bigint COMMENT '当日活跃设备',
`new_m_count` bigint COMMENT '当日新增设备',
`new_m_ratio` decimal(10,2) COMMENT '当日新增占日活的比率'
) COMMENT '每日活跃用户数量'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_user_convert_day/'
;
1)数据导入
hive (gmall)>
insert into table ads_user_convert_day
select
'2019-02-10',
sum( uc.dc) sum_dc,
sum( uc.nmc) sum_nmc,
cast(sum( uc.nmc)/sum( uc.dc)*100 as decimal(10,2)) new_m_ratio
from
(
select
day_count dc,
0 nmc
from ads_uv_count
where dt='2019-02-10'
union all
select
0 dc,
new_mid_count nmc
from ads_new_mid_count
where create_date='2019-02-10'
)uc;
2)查看导入数据
hive (gmall)>
select * from ads_user_convert_day;
hive (gmall)>
drop table if exists ads_user_action_convert_day;
create table ads_user_action_convert_day(
`dt` string COMMENT '统计日期',
`total_visitor_m_count` bigint COMMENT '总访问人数',
`order_u_count` bigint COMMENT '下单人数',
`visitor2order_convert_ratio` decimal(10,2) COMMENT '访问到下单转化率',
`payment_u_count` bigint COMMENT '支付人数',
`order2payment_convert_ratio` decimal(10,2) COMMENT '下单到支付的转化率'
) COMMENT '每日用户行为转化率统计'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_user_convert_day/'
;
1)数据导入
hive (gmall)>
insert into table ads_user_action_convert_day
select
'2019-02-10',
uv.day_count,
ua.order_count,
cast(ua.order_count/uv.day_count*100 as decimal(10,2)) visitor2order_convert_ratio,
ua.payment_count,
cast(ua.payment_count/ua.order_count*100 as decimal(10,2)) order2payment_convert_ratio
from
(
select
sum(if(order_count>0,1,0)) order_count,
sum(if(payment_count>0,1,0)) payment_count
from dws_user_action
where dt='2019-02-10'
)ua, ads_uv_count uv
where uv.dt='2019-02-10'
;
2)查询导入数据
hive (gmall)> select * from ads_user_action_convert_day;
需求:以月为单位统计,购买2次以上商品的用户
hive (gmall)>
drop table if exists dws_sale_detail_daycount;
create external table dws_sale_detail_daycount
( user_id string comment '用户 id',
sku_id string comment '商品 Id',
user_gender string comment '用户性别',
user_age string comment '用户年龄',
user_level string comment '用户等级',
order_price decimal(10,2) comment '订单价格',
sku_name string comment '商品名称',
sku_tm_id string comment '品牌id',
sku_category3_id string comment '商品三级品类id',
sku_category2_id string comment '商品二级品类id',
sku_category1_id string comment '商品一级品类id',
sku_category3_name string comment '商品三级品类名称',
sku_category2_name string comment '商品二级品类名称',
sku_category1_name string comment '商品一级品类名称',
spu_id string comment '商品 spu',
sku_num int comment '购买个数',
order_count string comment '当日下单单数',
order_amount string comment '当日下单金额'
) COMMENT '用户购买商品明细表'
PARTITIONED BY ( `dt` string)
stored as parquet
location '/warehouse/gmall/dws/dws_user_sale_detail_daycount/'
tblproperties ("parquet.compression"="snappy");
hive (gmall)>
with
tmp_detail as
(
select
user_id,
sku_id,
sum(sku_num) sku_num ,
count(*) order_count ,
sum(od.order_price*sku_num) order_amount
from ods_order_detail od
where od.dt='2019-02-10' and user_id is not null
group by user_id, sku_id
)
insert overwrite table dws_sale_detail_daycount partition(dt='2019-02-10')
select
tmp_detail.user_id,
tmp_detail.sku_id,
u.gender,
months_between('2019-02-10', u.birthday)/12 age,
u.user_level,
price,
sku_name,
tm_id,
category3_id ,
category2_id ,
category1_id ,
category3_name ,
category2_name ,
category1_name ,
spu_id,
tmp_detail.sku_num,
tmp_detail.order_count,
tmp_detail.order_amount
from tmp_detail
left join dwd_user_info u on u.id=tmp_detail.user_id and u.dt='2019-02-10'
left join dwd_sku_info s on tmp_detail.sku_id =s.id and s.dt='2019-02-10'
;
1)在/home/newbies/bin目录下创建脚本dws_sale.sh
[newbies@hadoop102 bin]$ vim dws_sale.sh
在脚本中填写如下内容
#!/bin/bash
# 定义变量方便修改
APP=gmall
hive=/opt/module/hive/bin/hive
# 如果是输入的日期按照取输入日期;如果没输入日期取当前时间的前一天
if [ -n $1 ] ;then
log_date=$1
else
log_date=`date -d "-1 day" +%F`
fi
sql="
set hive.exec.dynamic.partition.mode=nonstrict;
with
tmp_detail as
(
select
user_id,
sku_id,
sum(sku_num) sku_num ,
count(*) order_count ,
sum(od.order_price*sku_num) order_amount
from "$APP".ods_order_detail od
where od.dt='$log_date' and user_id is not null
group by user_id, sku_id
)
insert overwrite table "$APP".dws_sale_detail_daycount partition(dt='$log_date')
select
tmp_detail.user_id,
tmp_detail.sku_id,
u.gender,
months_between('$log_date', u.birthday)/12 age,
u.user_level,
price,
sku_name,
tm_id,
category3_id ,
category2_id ,
category1_id ,
category3_name ,
category2_name ,
category1_name ,
spu_id,
tmp_detail.sku_num,
tmp_detail.order_count,
tmp_detail.order_amount
from tmp_detail
left join "$APP".dwd_user_info u
on u.id=tmp_detail.user_id and u.dt='$log_date'
left join "$APP".dwd_sku_info s on tmp_detail.sku_id =s.id and s.dt='$log_date';
"
$hive -e "$sql"
2)增加脚本执行权限
[newbies@hadoop102 bin]$ chmod 777 dws_sale.sh
3)执行脚本导入数据
[newbies@hadoop102 bin]$ dws_sale.sh 2019-02-11
4)查看导入数据
hive (gmall)>
select * from dws_sale_detail_daycount where dt='2019-02-11' limit 2;
hive (gmall)>
drop table ads_sale_tm_category1_stat_mn;
create table ads_sale_tm_category1_stat_mn
(
tm_id string comment '品牌id ' ,
category1_id string comment '1级品类id ',
category1_name string comment '1级品类名称 ',
buycount bigint comment '购买人数',
buy_twice_last bigint comment '两次以上购买人数',
buy_twice_last_ratio decimal(10,2) comment '单次复购率',
buy_3times_last bigint comment '三次以上购买人数',
buy_3times_last_ratio decimal(10,2) comment '多次复购率' ,
stat_mn string comment '统计月份',
stat_date string comment '统计日期'
) COMMENT '复购率统计'
row format delimited fields terminated by '\t'
location '/warehouse/gmall/ads/ads_sale_tm_category1_stat_mn/'
;
1)数据导入
hive (gmall)>
insert into table ads_sale_tm_category1_stat_mn
select
mn.sku_tm_id,
mn.sku_category1_id,
mn.sku_category1_name,
sum(if(mn.order_count>=1,1,0)) buycount,
sum(if(mn.order_count>=2,1,0)) buyTwiceLast,
sum(if(mn.order_count>=2,1,0))/sum( if(mn.order_count>=1,1,0)) buyTwiceLastRatio,
sum(if(mn.order_count>3,1,0)) buy3timeLast ,
sum(if(mn.order_count>=3,1,0))/sum( if(mn.order_count>=1,1,0)) buy3timeLastRatio ,
date_format('2019-02-10' ,'yyyy-MM') stat_mn,
'2019-02-10' stat_date
from
(
select od.sku_tm_id,
od.sku_category1_id,
od.sku_category1_name,
user_id ,
sum(order_count) order_count
from dws_sale_detail_daycount od
where
date_format(dt,'yyyy-MM')<=date_format('2019-02-10' ,'yyyy-MM')
group by
od.sku_tm_id, od.sku_category1_id, user_id, od.sku_category1_name
) mn
group by mn.sku_tm_id, mn.sku_category1_id, mn.sku_category1_name
;
2)查询导入数据
hive (gmall)> select * from ads_sale_tm_category1_stat_mn;
1)在/home/newbies/bin目录下创建脚本ads_sale.sh
[newbies@hadoop102 bin]$ vim ads_sale.sh
在脚本中填写如下内容
#!/bin/bash
# 定义变量方便修改
APP=gmall
hive=/opt/module/hive/bin/hive
# 如果是输入的日期按照取输入日期;如果没输入日期取当前时间的前一天
if [ -n $1 ] ;then
log_date=$1
else
log_date=`date -d "-1 day" +%F`
fi
sql="
set hive.exec.dynamic.partition.mode=nonstrict;
insert into table "$APP".ads_sale_tm_category1_stat_mn
select
mn.sku_tm_id,
mn.sku_category1_id,
mn.sku_category1_name,
sum(if(mn.order_count>=1,1,0)) buycount,
sum(if(mn.order_count>=2,1,0)) buyTwiceLast,
sum(if(mn.order_count>=2,1,0))/sum( if(mn.order_count>=1,1,0)) buyTwiceLastRatio,
sum(if(mn.order_count>3,1,0)) buy3timeLast ,
sum(if(mn.order_count>=3,1,0))/sum( if(mn.order_count>=1,1,0)) buy3timeLastRatio ,
date_format('$log_date' ,'yyyy-MM') stat_mn,
'$log_date' stat_date
from
(
select od.sku_tm_id,
od.sku_category1_id,
od.sku_category1_name,
user_id ,
sum(order_count) order_count
from "$APP".dws_sale_detail_daycount od
where date_format(dt,'yyyy-MM')<=date_format('$log_date' ,'yyyy-MM')
group by od.sku_tm_id, od.sku_category1_id, user_id, od.sku_category1_name
) mn
group by mn.sku_tm_id, mn.sku_category1_id, mn.sku_category1_name;
"
$hive -e "$sql"
2)增加脚本执行权限
[newbies@hadoop102 bin]$ chmod 777 ads_sale.sh
3)执行脚本导入数据
[newbies@hadoop102 bin]$ ads_sale.sh 2019-02-11
4)查看导入数据
hive (gmall)>
select * from ads_sale_tm_category1_stat_mn limit 2;
1)在MySQL中创建ads_sale_tm_category1_stat_mn表
create table ads_sale_tm_category1_stat_mn
(
tm_id varchar(200) comment '品牌id ' ,
category1_id varchar(200) comment '1级品类id ',
category1_name varchar(200) comment '1级品类名称 ',
buycount varchar(200) comment '购买人数',
buy_twice_last varchar(200) comment '两次以上购买人数',
buy_twice_last_ratio varchar(200) comment '单次复购率',
buy_3times_last varchar(200) comment '三次以上购买人数',
buy_3times_last_ratio varchar(200) comment '多次复购率' ,
stat_mn varchar(200) comment '统计月份',
stat_date varchar(200) comment '统计日期'
)
2)编写Sqoop导出脚本
在/home/newbies/bin目录下创建脚本sqoop_export.sh
[newbies@hadoop102 bin]$ vim sqoop_export.sh
在脚本中填写如下内容
#!/bin/bash
db_name=gmall
export_data() {
/opt/module/sqoop/bin/sqoop export \
--connect "jdbc:mysql://hadoop102:3306/${db_name}?useUnicode=true&characterEncoding=utf-8" \
--username root \
--password 000000 \
--table $1 \
--num-mappers 1 \
--export-dir /warehouse/$db_name/ads/$1 \
--input-fields-terminated-by "\t" \
--update-key "tm_id,category1_id,stat_mn,stat_date" \
--update-mode allowinsert \
--input-null-string '\\N' \
--input-null-non-string '\\N'
}
case $1 in
"ads_sale_tm_category1_stat_mn")
export_data "ads_sale_tm_category1_stat_mn"
;;
"all")
export_data "ads_sale_tm_category1_stat_mn"
;;
esac
关于导出update还是insert的问题
--update-mode
参数 :
updateonly 只更新,无法插入新数据
allowinsert 允许新增
--update-key
允许更新的情况下,指定哪些字段匹配视为同一条数据,进行更新而不增加。多个字段用逗号分隔。
3)执行Sqoop导出脚本
[newbies@hadoop102 bin]$ chmod 777 sqoop_export.sh
[newbies@hadoop102 bin]$ sqoop_export.sh all
4)在MySQL中查看结果
SELECT * FROM ads_sale_tm_category1_stat_mn;
1)每个等级,每种商品,买一次的用户数,买两次的用户数=》得出复购率
2)利用开窗函数,取每个等级的前十
3)形成脚本
================================ Begin =========================
2.1 安装前准备
1) 将Azkaban Web服务器、Azkaban执行服务器、Azkaban的sql执行脚本及MySQL安装包拷贝到hadoop102虚拟机/opt/software目录下
a) azkaban-web-server-2.5.0.tar.gz
b) azkaban-executor-server-2.5.0.tar.gz
c) azkaban-sql-script-2.5.0.tar.gz
d) mysql-libs.zip
2) 选择Mysql作为Azkaban数据库,因为Azkaban建立了一些Mysql连接增强功能,以方便Azkaban设置,并增强服务可靠性。(参见hive文档2.4)
2.2 安装Azkaban
1) 在/opt/module/目录下创建azkaban目录
[newbies@hadoop102 module]$ mkdir azkaban
2) 解压azkaban-web-server-2.5.0.tar.gz、azkaban-executor-server-2.5.0.tar.gz、azkaban-sql-script-2.5.0.tar.gz到/opt/module/azkaban目录下
[newbies@hadoop102 software]$ tar -zxvf azkaban-web-server-2.5.0.tar.gz -C /opt/module/azkaban/
[newbies@hadoop102 software]$ tar -zxvf azkaban-executor-server-2.5.0.tar.gz -C /opt/module/azkaban/
[newbies@hadoop102 software]$ tar -zxvf azkaban-sql-script-2.5.0.tar.gz -C /opt/module/azkaban/
3) 对解压后的文件重新命名
[newbies@hadoop102 azkaban]$ mv azkaban-web-2.5.0/ server
[newbies@hadoop102 azkaban]$ mv azkaban-executor-2.5.0/ executor
4) azkaban脚本导入
进入mysql,创建azkaban数据库,并将解压的脚本导入到azkaban数据库。
[newbies@hadoop102 azkaban]$ mysql -uroot -p000000
mysql> create database azkaban;
mysql> use azkaban;
mysql> source /opt/module/azkaban/azkaban-2.5.0/create-all-sql-2.5.0.sql
注:source后跟.sql文件,用于批量处理.sql文件中的sql语句。
Keytool是java数据证书的管理工具,使用户能够管理自己的公/私钥对及相关证书。
-keystore 指定密钥库的名称及位置(产生的各类信息将不在.keystore文件中)
-genkey 在用户主目录中创建一个默认文件".keystore"
-alias 对我们生成的.keystore 进行指认别名;如果没有默认是mykey
-keyalg 指定密钥的算法 RSA/DSA 默认是DSA
1)生成 keystore的密码及相应信息的密钥库
[newbies@hadoop102 azkaban]$ keytool -keystore keystore -alias jetty -genkey -keyalg RSA
输入密钥库口令:
再次输入新口令:
您的名字与姓氏是什么?
[Unknown]:
您的组织单位名称是什么?
[Unknown]:
您的组织名称是什么?
[Unknown]:
您所在的城市或区域名称是什么?
[Unknown]:
您所在的省/市/自治区名称是什么?
[Unknown]:
该单位的双字母国家/地区代码是什么?
[Unknown]:
CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown是否正确?
[否]: y
输入 的密钥口令
(如果和密钥库口令相同, 按回车):
再次输入新口令:
注意:
密钥库的密码至少必须6个字符,可以是纯数字或者字母或者数字和字母的组合等等
密钥库的密码最好和
2)将keystore 拷贝到 azkaban web服务器根目录中
[newbies@hadoop102 azkaban]$ mv keystore /opt/module/azkaban/server/
先配置好服务器节点上的时区
[newbies@hadoop102 azkaban]$ tzselect
Please identify a location so that time zone rules can be set correctly.
Please select a continent or ocean.
1) Africa
2) Americas
3) Antarctica
4) Arctic Ocean
5) Asia
6) Atlantic Ocean
7) Australia
8) Europe
9) Indian Ocean
10) Pacific Ocean
11) none - I want to specify the time zone using the Posix TZ format.
#? 5
Please select a country.
1) Afghanistan 18) Israel 35) Palestine
2) Armenia 19) Japan 36) Philippines
3) Azerbaijan 20) Jordan 37) Qatar
4) Bahrain 21) Kazakhstan 38) Russia
5) Bangladesh 22) Korea (North) 39) Saudi Arabia
6) Bhutan 23) Korea (South) 40) Singapore
7) Brunei 24) Kuwait 41) Sri Lanka
8) Cambodia 25) Kyrgyzstan 42) Syria
9) China 26) Laos 43) Taiwan
10) Cyprus 27) Lebanon 44) Tajikistan
11) East Timor 28) Macau 45) Thailand
12) Georgia 29) Malaysia 46) Turkmenistan
13) Hong Kong 30) Mongolia 47) United Arab Emirates
14) India 31) Myanmar (Burma) 48) Uzbekistan
15) Indonesia 32) Nepal 49) Vietnam
16) Iran 33) Oman 50) Yemen
17) Iraq 34) Pakistan
#? 9
Please select one of the following time zone regions.
1) Beijing Time
2) Xinjiang Time
#? 1
The following information has been given:
China
Beijing Time
Therefore TZ='Asia/Shanghai' will be used.
Local time is now: Thu Oct 18 16:24:23 CST 2018.
Universal Time is now: Thu Oct 18 08:24:23 UTC 2018.
Is the above information OK?
1) Yes
2) No
#? 1
You can make this change permanent for yourself by appending the line
TZ='Asia/Shanghai'; export TZ
to the file '.profile' in your home directory; then log out and log in again.
Here is that TZ value again, this time on standard output so that you
can use the /usr/bin/tzselect command in shell scripts:
Asia/Shanghai
2)拷贝该时区文件,覆盖系统本地时区配置
[newbies@hadoop102 azkaban]$ cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
3)集群时间同步(同时发给三个窗口)
[newbies@hadoop102 azkaban]$ sudo date -s '2018-10-18 16:39:30'
1)进入azkaban web服务器安装目录 conf目录,打开azkaban.properties文件
[newbies@hadoop102 conf]$ pwd
/opt/module/azkaban/server/conf
[newbies@hadoop102 conf]$ vim azkaban.properties
2)按照如下配置修改azkaban.properties文件。
#Azkaban Personalization Settings
#服务器UI名称,用于服务器上方显示的名字
azkaban.name=Test
#描述
azkaban.label=My Local Azkaban
#UI颜色
azkaban.color=#FF3601
azkaban.default.servlet.path=/index
#默认web server存放web文件的目录
web.resource.dir=/opt/module/azkaban/server/web/
#默认时区,已改为亚洲/上海 默认为美国
default.timezone.id=Asia/Shanghai
#Azkaban UserManager class
user.manager.class=azkaban.user.XmlUserManager
#用户权限管理默认类(绝对路径)
user.manager.xml.file=/opt/module/azkaban/server/conf/azkaban-users.xml
#Loader for projects
#global配置文件所在位置(绝对路径)
executor.global.properties=/opt/module/azkaban/executor/conf/global.properties
azkaban.project.dir=projects
#数据库类型
database.type=mysql
#端口号
mysql.port=3306
#数据库连接IP
mysql.host=hadoop102
#数据库实例名
mysql.database=azkaban
#数据库用户名
mysql.user=root
#数据库密码
mysql.password=000000
#最大连接数
mysql.numconnections=100
# Velocity dev mode
velocity.dev.mode=false
# Azkaban Jetty server properties.
# Jetty服务器属性.
#最大线程数
jetty.maxThreads=25
#Jetty SSL端口
jetty.ssl.port=8443
#Jetty端口
jetty.port=8081
#SSL文件名(绝对路径)
jetty.keystore=/opt/module/azkaban/server/keystore
#SSL文件密码
jetty.password=000000
#Jetty主密码与keystore文件相同
jetty.keypassword=000000
#SSL文件名(绝对路径)
jetty.truststore=/opt/module/azkaban/server/keystore
#SSL文件密码
jetty.trustpassword=000000
# Azkaban Executor settings
executor.port=12321
# mail settings
mail.sender=
mail.host=
job.failure.email=
job.success.email=
lockdown.create.projects=false
cache.directory=cache
3)web服务器用户配置
在azkaban web服务器安装目录 conf目录,按照如下配置修改azkaban-users.xml 文件,增加管理员用户。
[newbies@hadoop102 conf]$ vim azkaban-users.xml
1)进入执行服务器安装目录conf,打开azkaban.properties
[newbies@hadoop102 conf]$ pwd
/opt/module/azkaban/executor/conf
[newbies@hadoop102 conf]$ vim azkaban.properties
2)按照如下配置修改azkaban.properties文件。
#Azkaban
#时区
default.timezone.id=Asia/Shanghai
# Azkaban JobTypes Plugins
#jobtype 插件所在位置
azkaban.jobtype.plugin.dir=plugins/jobtypes
#Loader for projects
executor.global.properties=/opt/module/azkaban/executor/conf/global.properties
azkaban.project.dir=projects
database.type=mysql
mysql.port=3306
mysql.host=hadoop102
mysql.database=azkaban
mysql.user=root
mysql.password=000000
mysql.numconnections=100
# Azkaban Executor settings
#最大线程数
executor.maxThreads=50
#端口号(如修改,请与web服务中一致)
executor.port=12321
#线程数
executor.flow.threads=30
在executor服务器目录下执行启动命令
[newbies@hadoop102 executor]$ pwd
/opt/module/azkaban/executor
[newbies@hadoop102 executor]$ bin/azkaban-executor-start.sh
在azkaban web服务器目录下执行启动命令
[newbies@hadoop102 server]$ pwd
/opt/module/azkaban/server
[newbies@hadoop102 server]$ bin/azkaban-web-start.sh
注意:
先执行executor,再执行web,避免Web Server会因为找不到执行器启动失败。
jps查看进程
[newbies@hadoop102 server]$ jps
3601 AzkabanExecutorServer
5880 Jps
3661 AzkabanWebServer
启动完成后,在浏览器(建议使用谷歌浏览器)中输入https://服务器IP地址:8443,即可访问azkaban服务了。
在登录中输入刚才在azkaban-users.xml文件中新添加的户用名及密码,点击 login。
Azkaba内置的任务类型支持command、java
1)创建job描述文件
[newbies@hadoop102 jobs]$ vim first.job
#first.job
type=command
command=echo 'this is my first job'
2) 将job资源文件打包成zip文件
[newbies@hadoop102 jobs]$ zip first.zip first.job
adding: first.job (deflated 15%)
[newbies@hadoop102 jobs]$ ll
总用量 8
-rw-rw-r--. 1 newbies newbies 60 10月 18 17:42 first.job
-rw-rw-r--. 1 newbies newbies 219 10月 18 17:43 first.zip
注意:
目前,Azkaban上传的工作流文件只支持xxx.zip文件。zip应包含xxx.job运行作业所需的文件和任何文件(文件名后缀必须以.job结尾,否则无法识别)。作业名称在项目中必须是唯一的。
3)通过azkaban的web管理平台创建project并上传job的zip包
首先创建project
上传zip包
4)启动执行该job
点击执行工作流
点击继续
5)Job执行成功
6)点击查看job日志
1)创建有依赖关系的多个job描述
第一个job:start.job
[newbies@hadoop102 jobs]$ vim start.job
#start.job
type=command
command=touch /opt/module/kangkang.txt
第二个job:step1.job依赖start.job
[newbies@hadoop102 jobs]$ vim step1.job
#step1.job
type=command
dependencies=start
command=echo "this is step1 job"
第三个job:step2.job依赖start.job
[newbies@hadoop102 jobs]$ vim step2.job
#step2.job
type=command
dependencies=start
command=echo "this is step2 job"
第四个job:finish.job依赖step1.job和step2.job
[newbies@hadoop102 jobs]$ vim finish.job
#finish.job
type=command
dependencies=step1,step2
command=echo "this is finish job"
2)将所有job资源文件打到一个zip包中
[newbies@hadoop102 jobs]$ zip jobs.zip start.job step1.job step2.job finish.job
updating: start.job (deflated 16%)
adding: step1.job (deflated 12%)
adding: step2.job (deflated 12%)
adding: finish.job (deflated 14%)
3)在azkaban的web管理界面创建工程并上传zip包
4)启动工作流flow
6)查看结果
思考:
将student.txt文件上传到hdfs,根据所传文件创建外部表,再将表中查询到的结果写入到本地文件
使用Azkaban调度java程序
1)编写java程序
import java.io.IOException;
public class AzkabanTest {
public void run() throws IOException {
// 根据需求编写具体代码
FileOutputStream fos = new FileOutputStream("/opt/module/azkaban/output.txt");
fos.write("this is a java progress".getBytes());
fos.close();
}
public static void main(String[] args) throws IOException {
AzkabanTest azkabanTest = new AzkabanTest();
azkabanTest.run();
}
}
2)将java程序打成jar包,创建lib目录,将jar放入lib内
[newbies@hadoop102 azkaban]$ mkdir lib
[newbies@hadoop102 azkaban]$ cd lib/
[newbies@hadoop102 lib]$ ll
总用量 4
-rw-rw-r--. 1 newbies newbies 3355 10月 18 20:55 azkaban-0.0.1-SNAPSHOT.jar
3)编写job文件
[newbies@hadoop102 jobs]$ vim azkabanJava.job
#azkabanJava.job
type=javaprocess
java.class=com.newbies.azkaban.AzkabanTest
classpath=/opt/module/azkaban/lib/*
4)将job文件打成zip包
[newbies@hadoop102 jobs]$ zip azkabanJava.zip azkabanJava.job
adding: azkabanJava.job (deflated 19%)
5)通过azkaban的web管理平台创建project并上传job压缩包,启动执行该job
[newbies@hadoop102 azkaban]$ pwd
/opt/module/azkaban
[newbies@hadoop102 azkaban]$ ll
总用量 24
drwxrwxr-x. 2 newbies newbies 4096 10月 17 17:14 azkaban-2.5.0
drwxrwxr-x. 10 newbies newbies 4096 10月 18 17:17 executor
drwxrwxr-x. 2 newbies newbies 4096 10月 18 20:35 jobs
drwxrwxr-x. 2 newbies newbies 4096 10月 18 20:54 lib
-rw-rw-r--. 1 newbies newbies 23 10月 18 20:55 output
drwxrwxr-x. 9 newbies newbies 4096 10月 18 17:17 server
[newbies@hadoop102 azkaban]$ cat output
this is a java progress
1)创建job描述文件
[newbies@hadoop102 jobs]$ vim fs.job
#hdfs job
type=command
command=/opt/module/hadoop-2.7.2/bin/hadoop fs -mkdir /azkaban
2)将job资源文件打包成zip文件
[newbies@hadoop102 jobs]$ zip fs.zip fs.job
adding: fs.job (deflated 12%)
3)通过azkaban的web管理平台创建project并上传job压缩包
4)启动执行该job
5)查看结果
mapreduce任务依然可以使用azkaban进行调度
1)创建job描述文件,及mr程序jar包
[newbies@hadoop102 jobs]$ vim mapreduce.job
#mapreduce job
type=command
command=/opt/module/hadoop-2.7.2/bin/hadoop jar /opt/module/hadoop-2.7.2/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.2.jar wordcount /wordcount/input /wordcount/output
2) 将所有job资源文件打到一个zip包中
[newbies@hadoop102 jobs]$ zip mapreduce.zip mapreduce.job
adding: mapreduce.job (deflated 43%)
3)在azkaban的web管理界面创建工程并上传zip包
4)启动job
5)查看结果
1)创建job描述文件和hive脚本
(1)Hive脚本:student.sql
[newbies@hadoop102 jobs]$ vim student.sql
use default;
drop table student;
create table student(id int, name string)
row format delimited fields terminated by '\t';
load data local inpath '/opt/module/datas/student.txt' into table student;
insert overwrite local directory '/opt/module/datas/student'
row format delimited fields terminated by '\t'
select * from student;
(2)Job描述文件:hive.job
[newbies@hadoop102 jobs]$ vim hive.job
#hive job
type=command
command=/opt/module/hive/bin/hive -f /opt/module/azkaban/jobs/student.sql
2) 将所有job资源文件打到一个zip包中
[newbies@hadoop102 jobs]$ zip hive.zip hive.job
adding: hive.job (deflated 21%)
3)在azkaban的web管理界面创建工程并上传zip包
4)启动job
5)查看结果
[newbies@hadoop102 student]$ cat /opt/module/datas/student/000000_0
1001 yangyang
1002 bobo
1003 banzhang
1004 pengpeng
1)生成数据
CALL init_data('2019-02-12',300,200,300,FALSE);
2)编写Azkaban程序运行job.
(1)import文件
type=command
do_date=${dt}
command=/home/newbies/bin/sqoop_import.sh all ${do_date}
(2)ods文件
type=command
do_date=${dt}
dependencies=import
command=/home/newbies/bin/ods_db.sh ${do_date}
(3)dwd文件
type=command
do_date=${dt}
dependencies=ods
command=/home/newbies/bin/dwd_db.sh ${do_date}
(4)dws文件
type=command
do_date=${dt}
dependencies=dwd
command=/home/newbies/bin/dws_sale.sh ${do_date}
(5)ads文件
type=command
do_date=${dt}
dependencies=dws
command=/home/newbies/bin/ads_sale.sh ${do_date}
(6)export文件
type=command
do_date=${dt}
dependencies=ads
command=/home/newbies/bin/sqoop_export.sh all ${do_date}
(7)将以上6个文件压缩成gmall-job.zip文件
3)创建Azkaban工程,并上传gmall-job.zip文件。
1)生成10条原始订单数据
CALL init_data('2019-02-13',10,5,10,TRUE);
[newbies@hadoop102 bin]$ sqoop_import.sh all 2019-02-13
[newbies@hadoop102 bin]$ ods_db.sh 2019-02-13
[newbies@hadoop102 bin]$ dwd_db.sh 2019-02-13
2)建立拉链表
hive (gmall)>
drop table if exists dwd_order_info_his;
create table dwd_order_info_his(
`id` string COMMENT '订单编号',
`total_amount` decimal(10,2) COMMENT '订单金额',
`order_status` string COMMENT '订单状态',
`user_id` string COMMENT '用户id' ,
`payment_way` string COMMENT '支付方式',
`out_trade_no` string COMMENT '支付流水号',
`create_time` string COMMENT '创建时间',
`operate_time` string COMMENT '操作时间' ,
`start_date` string COMMENT '有效开始日期',
`end_date` string COMMENT '有效结束日期'
) COMMENT '订单拉链表'
stored as parquet
location '/warehouse/gmall/dwd/dwd_order_info_his/'
tblproperties ("parquet.compression"="snappy");
3)初始化拉链表
hive (gmall)>
insert overwrite table dwd_order_info_his
select
id,
total_amount,
order_status,
user_id,
payment_way,
out_trade_no,
create_time,
operate_time,
'2019-02-13',
'9999-99-99'
from ods_order_info oi
where oi.dt='2019-02-13';
4)查询拉链表中数据
hive (gmall)> select * from dwd_order_info_his limit 2;
1)如何获得每日变动表
(1)最好表内有创建时间和变动时间(Lucky!)
(2)如果没有,可以利用第三方工具监控比如canal,监控MySQL的实时变化进行记录(麻烦)。
(3)逐行对比前后两天的数据, 检查md5(concat(全部有可能变化的字段))是否相同(low)
(4)要求业务数据库提供变动流水(人品,颜值)
2)因为dwd_order_info本身导入过来就是新增变动明细的表,所以不用处理
(1)2019-02-14日新增2条订单数据
CALL init_data('2019-02-14',2,5,10,TRUE);
(2)通过Sqoop把2019-02-14日所有数据导入
sqoop_import.sh all 2019-02-14
(3)ODS层数据导入
ods_db.sh 2019-02-14
(4)DWD层数据导入
dwd_db.sh 2019-02-14
1)建立临时表
hive (gmall)>
drop table if exists dwd_order_info_his_tmp;
create external table dwd_order_info_his_tmp(
`id` string COMMENT '订单编号',
`total_amount` decimal(10,2) COMMENT '订单金额',
`order_status` string COMMENT '订单状态',
`user_id` string COMMENT '用户id' ,
`payment_way` string COMMENT '支付方式',
`out_trade_no` string COMMENT '支付流水号',
`create_time` string COMMENT '创建时间',
`operate_time` string COMMENT '操作时间',
`start_date` string COMMENT '有效开始日期',
`end_date` string COMMENT '有效结束日期'
) COMMENT '订单拉链临时表'
stored as parquet
location '/warehouse/gmall/dwd/dwd_order_info_his_tmp/'
tblproperties ("parquet.compression"="snappy");
2)导入脚本
hive (gmall)>
insert overwrite table dwd_order_info_his_tmp
select * from
(
select
id,
total_amount ,
order_status ,
user_id ,
payment_way ,
out_trade_no,
create_time ,
operate_time ,
'2019-02-14' start_date,
'9999-99-99' end_date
from dwd_order_info where dt='2019-02-14'
union all
select oh.id,
oh.total_amount ,
oh.order_status ,
oh.user_id ,
oh.payment_way ,
oh.out_trade_no,
oh.create_time ,
oh.operate_time ,
oh.start_date,
if(oi.id is null ,oh.end_date, date_add(oi.dt,-1)) end_date
from dwd_order_info_his oh left join
(
select
*
from dwd_order_info
where dt='2019-02-14'
) oi
on oh.id=oi.id and oh.end_date='9999-99-99'
)his
order by his.id, start_date;
1)导入数据
hive (gmall)>
insert overwrite table dwd_order_info_his
select * from dwd_order_info_his_tmp;
2)查询导入数据
hive (gmall)> select * from dwd_order_info_his ;
1)下载地址
https://repo1.maven.org/maven2/com/facebook/presto/presto-server/0.196/presto-server-0.196.tar.gz
2)将presto-server-0.196.tar.gz导入hadoop102的/opt/software目录下,并解压到/opt/module目录
[newbies@hadoop102 software]$ tar -zxvf presto-server-0.196.tar.gz -C /opt/module/
3)修改名称为presto
[newbies@hadoop102 module]$ mv presto-server-0.196/ presto
4)进入到/opt/module/presto目录,并创建存储数据文件夹
[newbies@hadoop102 presto]$ mkdir data
5)进入到/opt/module/presto目录,并创建存储配置文件文件夹
[newbies@hadoop102 presto]$ mkdir etc
6)配置在/opt/module/presto/etc目录下添加jvm.config配置文件
[newbies@hadoop102 etc]$ vim jvm.config
添加如下内容
-server
-Xmx16G
-XX:+UseG1GC
-XX:G1HeapRegionSize=32M
-XX:+UseGCOverheadLimit
-XX:+ExplicitGCInvokesConcurrent
-XX:+HeapDumpOnOutOfMemoryError
-XX:+ExitOnOutOfMemoryError
7)Presto可以支持多个数据源,在Presto里面叫catalog,这里我们配置支持Hive的数据源,配置一个Hive的catalog
[newbies@hadoop102 etc]$ mkdir catalog
[newbies@hadoop102 catalog]$ vim hive.properties
添加如下内容
connector.name=hive-hadoop2
hive.metastore.uri=thrift://hadoop102:9083
8)将hadoop102上的presto分发到hadoop103、hadoop104
[newbies@hadoop102 module]$ xsync presto
9)解压之后,分别进入hadoop102、hadoop103、hadoop104三台主机的/opt/module/presto/etc的路径。配置node属性,node id每个节点都不一样。
[newbies@hadoop102 etc]$vim node.properties
node.environment=production
node.id=ffffffff-ffff-ffff-ffff-ffffffffffff
node.data-dir=/opt/module/presto/data
[newbies@hadoop103 etc]$vim node.properties
node.environment=production
node.id=ffffffff-ffff-ffff-ffff-fffffffffffe
node.data-dir=/opt/module/presto/data
[newbies@hadoop104 etc]$vim node.properties
node.environment=production
node.id=ffffffff-ffff-ffff-ffff-fffffffffffd
node.data-dir=/opt/module/presto/data
10)Presto是由一个coordinator节点和多个worker节点组成。在hadoop102上配置成coordinator,在hadoop103、hadoop104上配置为worker。
(1)hadoop102上配置coordinator节点
[newbies@hadoop102 etc]$ vim config.properties
添加内容如下
coordinator=true
node-scheduler.include-coordinator=false
http-server.http.port=8881
query.max-memory=50GB
discovery-server.enabled=true
discovery.uri=http://hadoop102:8881
(2)hadoop103、hadoop104上配置worker节点
[newbies@hadoop103 etc]$ vim config.properties
添加内容如下
coordinator=false
http-server.http.port=8881
query.max-memory=50GB
discovery.uri=http://hadoop102:8881
[newbies@hadoop104 etc]$ vim config.properties
添加内容如下
coordinator=false
http-server.http.port=8881
query.max-memory=50GB
discovery.uri=http://hadoop102:8881
11)在/opt/module/hive目录下,启动Hive Metastore,用newbies角色
nohup bin/hive --service metastore >/dev/null 2>&1 &
12)分别在hadoop102、hadoop103、hadoop104上启动presto server
(1)前台启动presto,控制台显示日志
[newbies@hadoop102 presto]$ bin/launcher run
[newbies@hadoop103 presto]$ bin/launcher run
[newbies@hadoop104 presto]$ bin/launcher run
(2)后台启动presto
[newbies@hadoop102 presto]$ bin/launcher start
[newbies@hadoop103 presto]$ bin/launcher start
[newbies@hadoop104 presto]$ bin/launcher start
13)日志查看路径/opt/module/presto/data/var/log
1)下载Presto的客户端
https://repo1.maven.org/maven2/com/facebook/presto/presto-cli/0.196/presto-cli-0.196-executable.jar
2)将presto-cli-0.196-executable.jar上传到hadoop102的/opt/module/presto文件夹下
3)修改文件名称
[newbies@hadoop102 presto]$ mv presto-cli-0.196-executable.jar prestocli
4)增加执行权限
[newbies@hadoop102 presto]$ chmod +x prestocli
5)启动prestocli
[newbies@hadoop102 presto]$ ./prestocli --server hadoop102:8881 --catalog hive --schema default
6)Presto命令行操作
Presto的命令行操作,相当于hive命令行操作,不过没有use命令。每个表必须要加上schema。
例如:
select * from schema.table limit 100
1)将yanagishima-18.0.zip上传到hadoop102的/opt/module目录
2)解压缩yanagishima
[newbies@hadoop102 module]$ unzip yanagishima-18.0.zip
cd yanagishima-18.0
3)进入到/opt/module/yanagishima-18.0/conf文件夹,编写yanagishima.properties配置
[newbies@hadoop102 conf]$ vim yanagishima.properties
添加如下内容
jetty.port=7080
presto.datasources=atiguigu-presto
presto.coordinator.server.atiguigu-presto=http://hadoop102:8881
catalog.atiguigu-presto=hive
schema.atiguigu-presto=default
sql.query.engines=presto
4)在/opt/module/yanagishima-18.0路径下启动yanagishima
[newbies@hadoop102 yanagishima-18.0]$
nohup bin/yanagishima-start.sh >y.log 2>&1 &
5)启动web页面
http://hadoop102:7080
看到界面,进行查询了。
查看表结构
这里有个tree view,可以查看所有表的结构,包括schema、表、字段等。
比如执行 select * from hive.dw_weather.tmp_news_click limit 10,这个句子里hive这个词可以删掉,是上面配置的catalog
每个表后面都有个复制键,点一下会复制完整的表名,然后再上面框里面输入sql语句,ctrl+enter键执行显示结果