赞
踩
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 | 男 | zs@163.com | 2 | 2018-11-11 |
2 | 李四 | 2011-11-11 | 女 | ls@163.com | 3 | 2018-11-11 |
3 | 王五 | 2011-11-11 | 中性 | ww@163.com | 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 j<v_order_detail_num DO
- SET j=j+1;
- INSERT INTO order_detail (order_id , sku_id,sku_name ,img_url ,order_price,sku_num )
- VALUES (v_order_id , rand_num(1,sku_num),rand_string(10),CONCAT('http://',rand_string(40)) ,CAST(rand_num(20,5000) AS DECIMAL(10,2)), rand_num(1,5) );
- END WHILE;
- SET j=0;
- UNTIL i = max_num
- END REPEAT;
- COMMIT;
- END$$
-
- DELIMITER ;
-
-
- DELIMITER $$
-
- DROP PROCEDURE IF EXISTS `update_order`$$
- ## 随机让订单状态小于5的订单 发生状态改变
- CREATE DEFINER=`root`@`localhost` PROCEDURE `update_order`(operate_time_string VARCHAR(20))
- BEGIN
- DECLARE v_operate_time DATETIME DEFAULT NULL;
- SET v_operate_time=DATE_FORMAT(operate_time_string,'%Y-%m-%d');
- UPDATE order_info o SET o.`order_status`=o.`order_status`+rand_num_seed(0,1,o.id) ,operate_time= IF( rand_num_seed(0,1,o.id) >0 , 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
-
- 输入 <jetty> 的密钥口令
- (如果和密钥库口令相同, 按回车):
- 再次输入新口令:
注意:
密钥库的密码至少必须6个字符,可以是纯数字或者字母或者数字和字母的组合等等
密钥库的密码最好和<jetty> 的密钥相同,方便记忆
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
- <azkaban-users>
- <user username="azkaban" password="azkaban" roles="admin" groups="azkaban" />
- <user username="metrics" password="metrics" roles="metrics"/>
- <user username="admin" password="admin" roles="admin,metrics" />
- <role name="admin" permissions="ADMIN" />
- <role name="metrics" permissions="METRICS"/>
- </azkaban-users>
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键执行显示结果
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。