日志数据用MR程序读的时候要对数据进行清洗,集成(地理位置 user_info)和转换(CSV json)在导入到hive中,单也有写数据不用清洗直接就可以导入到hive中用sql语句进行预处理,最后会得到一个完整的大宽表ODS的原始数据层,每行找一个全局id(guid)打一个标记,因为有可能好几行的数据访问量都是一个问的所以不能定义为多个客户,要定义为一个客户访问(在这里就是账号id或者设备id)
将数据导入到虚拟机
将hive year hdfs都打开 在进入到beeline导入数据
先建个表导入数据
create table tb_log(
log string
)
partitioned by(dt string)
;
load data local inpath "/data/log.log" into table tb_log partition(dt='20201007');
在重新传到别的表里加一个guid列且将数据通过json_tuple,改成表格数据就算简单的清理完成了
create table tb_ods_log as
select
if(account='' ,deviceId , account) as guid,
*
from
(select
json_tuple(
log ,
'account' ,'appId' ,'appVersion','carrier','deviceId','deviceType','eventId','ip','latitude','longitude','netType','osName','osVersion','properties','releaseChannel','resolution','sessionId' ,'timeStamp')
as
(account ,appId ,appVersion,carrier,deviceId,deviceType,eventId,ip,latitude,longitude,netType,osName,osVersion,properties,releaseChannel,resolution,sessionId ,`timeStamp`)
from
tb_log)t
where account != '' or deviceId !='' ;
在clickhouse中建表格式跟那边的一样
create table tb_ods_log(
guid String ,
account String ,
appId String ,
appVersion String ,
carrier String ,
deviceId String ,
deviceType String ,
eventId String ,ip String ,
latitude String ,
longitude String ,
netType String ,
osName String ,
osVersion String ,
properties String ,
releaseChannel String ,
resolution String ,
sessionId String ,
`timeStamp` String
) engine = MergeTree
order by guid ;
把hive中的表传到linux上并且指定分隔符
insert overwrite local directory '/data/'
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
select * from tb_ods_log;
把linux上的文件传到clinckhouse上
cat 000000_0 | clickhouse-client -q "insert into tb_ods_log FORMAT TSV"
在建一个 表跟他一样但是按时间排序了
create table tb_ods_log2 engine = MergeTree order by (guid,`timeStamp`)
as select * from tb_ods_log ;
这个代码块是关于事件的一个小知识点的补充
uid1 event1 1551398404
uid1 event2 1551398406
uid1 event3 1551398408
uid2 event2 1551398412
uid2 event3 1551398415
uid3 event3 1551398410
uid3 event4 1551398413
CREATE TABLE
funnel_test(
uid String,
eventid String,
eventTime UInt64
) ENGINE = MergeTree PARTITION BY (uid, eventTime) ORDER BY (uid, eventTime) ;
clickhouse-client -q "insert into funnel_test FORMAT TSV" < event.data
┌─uid──┬─eventid─┬──eventTime─┐
│ uid1 │ event1 │ 1551398404 │
└──────┴─────────┴────────────┘
┌─uid──┬─eventid─┬──eventTime─┐
│ uid1 │ event2 │ 1551398406 │
└──────┴─────────┴────────────┘
┌─uid──┬─eventid─┬──eventTime─┐
│ uid1 │ event3 │ 1551398408 │
└──────┴─────────┴────────────┘
┌─uid──┬─eventid─┬──eventTime─┐
│ uid2 │ event2 │ 1551398412 │
└──────┴─────────┴────────────┘
┌─uid──┬─eventid─┬──eventTime─┐
│ uid2 │ event3 │ 1551398415 │
└──────┴─────────┴────────────┘
┌─uid──┬─eventid─┬──eventTime─┐
│ uid3 │ event3 │ 1551398410 │
└──────┴─────────┴────────────┘
┌─uid──┬─eventid─┬──eventTime─┐
│ uid3 │ event4 │ 1551398413 │
└──────┴─────────┴────────────┘
select
uid,
windowFunnel(4)(toDateTime(eventTime),eventid = 'event2',eventid = 'event3') as funnel
from
funnel_test
group by uid;
┌─uid──┬─funnel─┐
│ uid3 │ 0 │
│ uid1 │ 2 │
│ uid2 │ 2 │
└──────┴────────┘
select
uid,
windowFunnel(4)(toDateTime(eventTime),eventid = 'event1' ,eventid = 'event2',eventid = 'event3') as funnel
from
funnel_test
group by uid;
┌─uid──┬─funnel─┐
│ uid3 │ 0 │
│ uid1 │ 3 │
│ uid2 │ 0 │
└──────┴────────┘
统计用户操作到第四步有多少人第三步有多少人第二步有多少人第一步有多少人
根据用户分组根据时间排序就把所有的事件聚合到一起了,在统计固定的时间里用户的时间步数
select
a ,
fo ,
fo+th ,
fo+th+tw ,
fo+th+tw+one
from
(
select
count(1) as a ,
sum(if(funnel=4,1,0)) as fo ,
sum(if(funnel=3,1,0)) as th ,
sum(if(funnel=2,1,0)) as tw,
sum(if(funnel=1,1,0)) as one
from
(select
guid,
windowFunnel(1000000)(
toDateTime(cast(`timeStamp` as Int64)),
eventId = 'adShow' ,
eventId = 'adClick',
eventId = 'addCart' ,
eventId = 'submitOrder'
) as funnel
from
tb_ods_log2
group by guid )) ;
chickhouse是一个分布式的列式存储数据库
分布式的基本工作流程:
在每一台机器上都装chickhouse都创建一个tb_user表,在创建一个分布式表tb_dist_user engine=distributed(…)分布式表格式跟tb_user表是一样的当向这个表insert into数据时就会被随机分配到任意机器上的tb_user表中,操作都是操作tb_dist_user表,数据是传分不到tb_user上存储查询也是查询tb_dist_user表然后会从关联的服务器上拉去数据聚合汇总
为了保证数据的高可靠性高安全性我们要对数据存储副本就类似于hbase中的region,不同的是region存的是表的行范围数据,但是shard存储的是切片数据不是连续的,服务器配置文件的集群名在/etc/metrika.xml中配置的,也就是在etc下创建metrika.xml文件就会以居群的模式开启,如果不配是就是单节点启动互不相干,创建集群要加metrika.xml配置文件海要改comfig.xml配置文件把自己访问自己提取出来
配置好之后就可以用这个集群了
创建一个分布式表 和 每台机器的tb_a 关联
create table tb_a2(id UInt8, name String) ENGINE=Log; 在每台机器上都建个一样的表
insert into tb_a2 values(1,'zss1'); 每个表分别插入数据
insert into tb_a2 values(2,'zss2');
insert into tb_a2 values(3,'zss3');
create table 在建一个分布式表
dis_a(id UInt8, name String) 分布式表结构跟上面的一样
ENGINE=Distributed(linux, default, tb_a2, id);
参数1集群名 参数2数据库名 参数3关联表名 参数4分片字段也可以写rand()随机分片
注意分片字段是一个integer类型