点一下关注吧!!!非常感谢!!持续更新!!!
Java篇开始了!
目前开始更新 MyBatis,一起深入浅出!
目前已经更新到了:
- Hadoop(已更完)
- HDFS(已更完)
- MapReduce(已更完)
- Hive(已更完)
- Flume(已更完)
- Sqoop(已更完)
- Zookeeper(已更完)
- HBase(已更完)
- Redis (已更完)
- Kafka(已更完)
- Spark(已更完)
- Flink(已更完)
- ClickHouse(已更完)
- Kudu(已更完)
- Druid(已更完)
- Kylin(已更完)
- Elasticsearch(已更完)
- DataX(已更完)
- Tez(已更完)
- 数据挖掘(已更完)
- Prometheus(已更完)
- Grafana(已更完)
- 离线数仓(正在更新…)
章节内容
上节我们完成了如下的内容:
- 会员活跃度 WDS 与 ADS 导出到 MySQL
- 广告业务 需求分析
广告业务
基本介绍在上节已经完成,本节我们继续处理这块业务。
需求分析
事件日志数据样例:
{
"wzk_event": [{
"name": "goods_detail_loading",
"json": {
"entry": "3",
"goodsid": "0",
"loading_time": "80",
"action": "4",
"staytime": "68",
"showtype": "4"
},
"time": 1596225273755
}, {
"name": "loading",
"json": {
"loading_time": "18",
"action": "1",
"loading_type": "2",
"type": "3"
},
"time": 1596231657803
}, ...
采集的信息包括:
- 商品详情页加载:goods_detail_loading
- 商品列表:loading
- 消息通知:notification
- 商品评论:comment
- 收藏:favorites
- 点赞:praise
- 广告:ad
在广告的字段中,收集到的数据有:
- action 用户行为 0曝光 1曝光后点击 2购买
- duration 停留时长
- shop_id 商家id
- event_type “ad”
- ad_type 1JPG 2PNG 3GIF 4SWF
- show_style 0静态图 1动态图
- product_id 产品id
- place 广告位置 1首页 2左侧 3右侧 4列表页
- sort 排序位置
需求指标
点击次数统计(分时统计)
- 曝光次数、不同用户ID数、不同用户数
- 点击次数、不同用户ID数、不同用户数
- 购买次数、不同用户ID数、不同用户数
转化率-漏斗分析
- 点击率 = 点击次数/曝光次数
- 购买率 = 购买次数/点击次数
活动曝光效果评估
行为(曝光、点击、购买)、时间段、广告位、产品、统计对应的次数
时间段、广告位、商品,曝光次数最多的前N个
ODS层
建立新表
Hive启动之后,切换到 ods层,然后我们继续创建外部表,将数据映射到Hive中
use ods;
drop table if exists ods.ods_log_event;
CREATE EXTERNAL TABLE ods.ods_log_event(
`str` string
) PARTITIONED BY (`dt` string)
STORED AS TEXTFILE
LOCATION '/user/data/logs/event';
执行结果如下图所示:
编写脚本
vim /opt/wzk/hive/ods_load_event_log.sh
编写脚本,写入内容如下:
#!/bin/bash
source /etc/profile
if [ -n "$1" ]
then
do_date=$1
else
do_date=`date -d "-1 day" +%F`
fi
sql="
alter table ods.ods_log_event add partition (dt='$do_date');
"
hive -e "$sql"
写入的内容如下所示:
DWD层
ODS:分区,事件的主要信息在JSON串中(JSON数组),公共信息在另外一个JSON串中
ODS:解析JSON,从JSON串中,提取JSONArray数据,将公共信息从JSON串中解析出来,所有事件的明细
所有事件的明细,包括:
- 分区
- 事件(JSON串)
- 公共信息字段
所有事件的明细 => 广告JSON串即系 => 广告事件的明细
广告事件的明细:
- 分区
- 广告信息字段
- 公共信息字段
建立新表
Hive启动之后,切换到 dwd 层,然后我们继续创建外部表,将数据映射到Hive中:
所有事件的明细表:
use dwd;
-- 所有事件明细
drop table if exists dwd.dwd_event_log;
CREATE EXTERNAL TABLE dwd.dwd_event_log(
`device_id` string,
`uid` string,
`app_v` string,
`os_type` string,
`event_type` string,
`language` string,
`channel` string,
`area` string,
`brand` string,
`name` string,
`event_json` string,
`report_time` string)
PARTITIONED BY (`dt` string)
stored as parquet;
运行结果如下图所示:
与广告点击明细:
use dwd;
-- 与广告点击明细
drop table if exists dwd.dwd_ad;
CREATE TABLE dwd.dwd_ad(
`device_id` string,
`uid` string,
`app_v` string,
`os_type` string,
`event_type` string,
`language` string,
`channel` string,
`area` string,
`brand` string,
`report_time` string,
`duration` int,
`ad_action` int,
`shop_id` int,
`ad_type` int,
`show_style` smallint,
`product_id` int,
`place` string,
`sort` int,
`hour` string
)
PARTITIONED BY (`dt` string)
stored as parquet;
运行结果如下图所示:
UDF
UDF 是用户根据具体需求编写的自定义函数,用于处理 SQL 语言无法直接完成的复杂逻辑。数据仓库系统(如 Hive、Spark SQL、ClickHouse 等)内置了一些通用的函数,但当内置函数无法满足需求时,可以通过 UDF 实现自定义扩展。
UDF 的作用
实现复杂逻辑
通过 UDF,可以将复杂的业务逻辑封装成函数,以简化 SQL 代码。例如,根据自定义规则处理字符串、日期计算等。
提高代码复用性
将重复使用的逻辑封装成 UDF,便于在多个查询中调用,减少代码冗余。
扩展 SQL 的功能
内置函数的功能有限,通过自定义函数可以实现更复杂的计算,如机器学习模型的调用、特殊格式解析等。
优化性能
在某些场景下,使用 UDF 可以减少 SQL 中复杂逻辑的嵌套,从而优化查询性能。
JSON串解析
内建函数、UDF、SerDe(JSON是所有的信息)
详细内容参见 会员活跃度章节-JSON数据处理-UDF(处理JSONArray)
public class ParseJsonArray extends UDF {
public ArrayList<String> evaluate(String jsonStr) {
if (Strings.isNullOrEmpty(jsonStr)) {
return null;
}
try{
// 获取jsonArray
JSONArray jsonArray = JSON.parseArray(jsonStr);
ArrayList<String> lst = new ArrayList<>();
for(Object o: jsonArray) {
lst.add(o.toString());
}
return lst;
}catch (JSONException e){
return null;
}
}
}
编写脚本
vim /opt/wzk/hive/dwd_load_event_log.sh
编写的脚本内容如下:
USE dwd;
add jar /opt/wzk/hive-parse-json-array-1.0-SNAPSHOT-jar-with-dependencies.jar;
CREATE temporary function wzk_json_array AS 'icu.wzk.ParseJsonArray';
WITH tmp_start AS (
SELECT SPLIT(str, ' ')[7] AS line
FROM ods.ods_log_event
WHERE dt='$do_date'
)
-- 插入数据到目标表 dwd_event_log
INSERT OVERWRITE TABLE dwd.dwd_event_log
PARTITION (dt='$do_date')
SELECT
device_id,
uid,
app_v,
os_type,
event_type,
language,
channel,
area,
brand,
get_json_object(k, '$.name') AS name,
get_json_object(k, '$.json') AS json,
get_json_object(k, '$.time') AS time
FROM (
SELECT
get_json_object(line, '$.attr.device_id') AS device_id,
get_json_object(line, '$.attr.uid') AS uid,
get_json_object(line, '$.attr.app_v') AS app_v,
get_json_object(line, '$.attr.os_type') AS os_type,
get_json_object(line, '$.attr.event_type') AS event_type,
get_json_object(line, '$.attr.language') AS language,
get_json_object(line, '$.attr.channel') AS channel,
get_json_object(line, '$.attr.area') AS area,
get_json_object(line, '$.attr.brand') AS brand,
get_json_object(line, '$.wzk_event') AS wzk_event,
line
FROM tmp_start
) A
LATERAL VIEW EXPLODE(wzk_json_array(line, 'wzk_event')) B AS k;
"
# 执行 Hive SQL
hive -e "$sql"
对应的截图如下所示:
从全部的事件日志中获取广告点击事件:
vim /opt/wzk/hive/dwd_load_ad_log.sh
写入内容如下所示:
#!/bin/bash
# 加载系统环境变量
source /etc/profile
# 确定操作日期,默认为前一天
if [ -n "$1" ]; then
do_date=$1
else
do_date=$(date -d "-1 day" +%F)
fi
# Hive SQL语句
sql="
INSERT OVERWRITE TABLE dwd.dwd_ad
PARTITION (dt='$do_date')
SELECT
device_id,
uid,
app_v,
os_type,
event_type,
language,
channel,
area,
brand,
report_time,
get_json_object(event_json, '$.duration') AS duration,
get_json_object(event_json, '$.ad_action') AS ad_action,
get_json_object(event_json, '$.shop_id') AS shop_id,
get_json_object(event_json, '$.ad_type') AS ad_type,
get_json_object(event_json, '$.show_style') AS show_style,
get_json_object(event_json, '$.product_id') AS product_id,
get_json_object(event_json, '$.place') AS place,
get_json_object(event_json, '$.sort') AS sort,
from_unixtime(ceil(report_time/1000), 'HH') AS report_hour
FROM dwd.dwd_event_log
WHERE dt='$do_date' AND name='ad';
"
# 执行 Hive SQL
hive -e "$sql"
对应的截图如下所示:
日志 => Flume => ODS => 清洗、转换 => 广告事件详细信息。