大数据-229 离线数仓 - ODS层的构建 Hive处理 JSON 数据处理 结构化
点一下关注吧!!!非常感谢!!持续更新!!!
Java篇开始了!
目前开始更新 MyBatis,一起深入浅出!
目前已经更新到了:
- Hadoop(已更完)
- HDFS(已更完)
- MapReduce(已更完)
- Hive(已更完)
- Flume(已更完)
- Sqoop(已更完)
- Zookeeper(已更完)
- HBase(已更完)
- Redis (已更完)
- Kafka(已更完)
- Spark(已更完)
- Flink(已更完)
- ClickHouse(已更完)
- Kudu(已更完)
- Druid(已更完)
- Kylin(已更完)
- Elasticsearch(已更完)
- DataX(已更完)
- Tez(已更完)
- 数据挖掘(已更完)
- Prometheus(已更完)
- Grafana(已更完)
- 离线数仓(正在更新…)
章节内容
上节我们完成了如下的内容:
- 自定义拦截器(续接上节) 编写代码
- 日志采集小结
整体结构
ODS层
ODS的定义
ODS是一种面向操作层的数据存储,专注于支持企业的日常运营。它通常整合了来自不同数据源(如ERP、CRM、销售系统等)的数据,通过清洗、转换后存储,以便快速查询和使用。ODS不以历史数据分析为主要目的,而是以操作和事务处理为核心。
ODS的特性
实时性或近实时性
ODS中的数据通常是实时或近实时的,能够快速反映业务系统中的最新状态,支持企业的及时决策。
数据整合
ODS整合来自多个源系统的数据,提供统一视图。它会通过ETL(提取、转换、加载)工具对数据进行处理。
非历史性
ODS数据的生命周期相对较短,通常只保存当前或最近的数据,不会长期存储历史数据。
面向操作
ODS的设计重点在于支持操作和事务处理,例如快速查询当前的客户订单状态,而不是复杂的分析或建模。
ODS的架构
ODS通常包含以下主要部分:
数据输入层数据输入层
从事务系统中提取原始数据(可能来自不同的数据源)。
使用ETL工具对数据进行初步清洗和转换。
数据存储层
存储经过整合的数据,通常以面向主题的形式组织。
数据存储可以是关系型数据库(如MySQL、PostgreSQL)或其他支持快速查询的数据库。
数据访问层
为操作型应用提供快速查询接口。
可能支持API、SQL查询或直接集成到企业应用中。
创建ODS层
我们启动Hive,进行建立:
ODS层的数据与源数据的格式基本相同,创建ODS层表:
use ods;
create external table ods.ods_start_log(
`str` string
) comment '用户启动日志信息'
partitioned by (`dt` string)
location '/user/data/logs/start';
执行结果如下图所示:
加载数据(测试用,可以不做测试)
-- 加载数据(测试时使用)
-- 加分区
alter table ods.ods_start_log add partition(dt='2020-08-02');
-- 删除分区
alter table ods.ods_start_log drop partition(dt='2020-08-02');
执行结果如下图所示:
这里可以看到使用的是:external 外部表的模式
加载ODS层数据
mkdir /opt/wzk/hive
vim /opt/wzk/hive/ods_load_startlog.sh
传参数确定日志,没有参数则取昨天日期
#!/bin/bash
APP=ODS
source /etc/profile
# 可以输入日期;如果未输入日期取昨天的时间
if [ -n "$1" ]
then
do_date=$1
else
do_date=`date -d "-1 day" +%F`
fi
# 定义要执行的SQL
sql="
alter table "$APP".ods_start_log add partition(dt='$do_date');
"
hive -e "$sql"
写入的内容如下图所示:
JSON数据处理
数据文件中每行必须要是一个完整的JSON字符串,一个JSON串不能穿越多行,Hive处理JSON数据总体来说有三个办法:
- 使用内建的函数get_json_obejct,json_tuple
- 使用自定义的UDF
- 第三方的SerDe
内建函数
get_json_object(string json_string, string path)
返回值:String
说明:解析JSON字符串json_string,返回path指定的内容,如果输入的JSON字符串无效,那么返回NULL,函数每次只返回一个数据项。
json_tuple(jsonStr, k1, k2…)
返回值:所有的输入参数,输出参数都是String
说明:参数为一组 k1,k2等等和JSON的字符串,返回值的元组,该方法比get_json_object高效,因此可以在一次调用中输入多个键
explode
使用explode将Hive一行中复杂的array或map结构拆分成多行。
测试数据
我们写入数据:
vim /opt/wzk/weibo.json
写入内容如下所示:
user1;18;male;{"id": 1,"ids": [101,102,103],"total_number": 3}
user2;20;female;{"id": 2,"ids":[201,202,203,204],"total_number": 4}
user3;23;male;{"id": 3,"ids":[301,302,303,304,305],"total_number": 5}
user4;17;male;{"id": 4,"ids": [401,402,403,304],"total_number":5}
user5;35;female;{"id": 5,"ids": [501,502,503],"total_number":3}
写入的结果如下图所示:
建表加载数据
启动Hive
hive
随后我们执行:
CREATE TABLE IF NOT EXISTS jsont1(
username string,
age int,
sex string,
json string
)
row format delimited fields terminated by ';';
load data local inpath '/opt/wzk/weibo.json' overwrite into table jsont1;
导入数据的结果如下图所示:
JSON数据的处理
-- get 单层值
SELECT
username, age, sex,
get_json_object(json, "$.id") id,
get_json_object(json, "$.ids") ids,
get_json_object(json, "$.total_number") num
FROM jsont1;
对应的查询结果如下图所示:
-- get 数组
SELECT
username, age, sex,
get_json_object(json, "$.id") id,
get_json_object(json, "$.ids[0]") ids0,
get_json_object(json, "$.ids[1]") ids1,
get_json_object(json, "$.ids[2]") ids2,
get_json_object(json, "$.ids[3]") ids3,
get_json_object(json, "$.total_number") num
FROM jsont1;
执行的结果如下图所示:
-- 使用 json_tuple 一次处理多个字段
SELECT
json_tuple(json, 'id', 'ids', 'total_number')
FROM jsont1;
执行的结果如下图所示:
-- 使用 explode + lateral view
-- 在上一步的基础上,再将数据展开
-- 第一步,将 [101,102,103] 中的 [ ] 替换掉
-- select "[101,102,103]"
-- select "101,102,103"
SELECT regexp_replace("[101,102,103]", "\\[|\\]", "");
-- 第二步,将上一步的字符串变为数组
SELECT split(regexp_replace("[101,102,103]", "\\[|\\]", ""), ",");
-- 第三步,使用explode + lateral view 将数据展开
SELECT username, age, sex, id, ids, num
FROM jsont1
lateral view json_tuple(json, 'id', 'ids', 'total_number') t1
AS id, ids, num;
with tmp AS (
SELECT username, age, sex, id, ids, num
FROM jsont1
lateral view json_tuple(json, 'id', 'ids', 'total_number') t1 AS id, ids, num)
SELECT username, age, sex, id, ids1, num
FROM tmp
lateral view explode(split(regexp_replace(ids, "\\[|\\]", ""), ",")) t1 AS ids1;
最终的执行结果如下图所示:
json_tuple 优点是一次可以解析多个JSON字段,对嵌套结果的解析操作复杂。