ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS),使用lz4压缩数据,压缩率高。
OLAP场景的关键特征:
在讲列式存储之前讲下行式存储,行式存储是处于同一行中的数据总是被物理的存储在一起。
常见的行式数据库系统有:MySQL
、Postgres
和MS SQL Server
。
Row | #0 | #1 | #2 | #N |
---|---|---|---|---|
WatchID | 89354350662 | 90329509958 | 89953706054 | … |
JavaEnable | 1 | 0 | 1 | … |
Title | Investor Relations | Contact us | Mission | … |
GoodEvent | 1 | 1 | 1 | … |
EventTime | 42508.22175925926 | 42508.34050925926 | 42508.31805555556 | … |
定义:
ods
是在数仓中存储业务系统源数据,所以从数据粒度、数据结构、数据关系等各个方面都与业务系统的数据源保持一致。
dim
以维度作为建模驱动,基于每个维度的业务含义,通过添加维度属性、关联维度等定义计算逻辑,完成属性定义的过程并建立一致的数据分析维表。为了避免在维度模型中冗余关联维度的属性,基于雪花模型构建维度表。(类似于基础表)
dwd
以业务过程作为建模驱动,基于每个具体的业务过程特点,构建最细粒度的明细事实表。可以结合企业的数据使用特点,将明细事实表的某些重要属性字段做适当冗余,也即宽表化处理。(类似于业务表)
dws
以分析的主题对象作为建模驱动,基于上层的应用和产品的指标需求,构建公共粒度的汇总指标表。以宽表化手段物理化模型,构建命名规范、口径一致的统计指标,为上层提供公共指标,建立汇总宽表、明细事实表。
ads
存放数据产品个性化的统计指标数据,根据CDM层与ODS层加工生成。
clickhouse表引擎非常丰富,有合并树引擎(MergeTree),日志引擎,集成的表引擎,在新建表时需要指定表引擎。
create table table_name(columns)
engine=engine_name
order by 主键
partition by 分区
SETTINGS index_granularity = n --间隔n行建立稀疏索引
MySQL引擎用于将远程的MySQL服务器中的表映射到ClickHouse中,并允许对表进行INSERT
和SELECT
查询,以方便在ClickHouse与MySQL之间进行数据交换。
创建数据库语句:
CREATE DATABASE [IF NOT EXISTS] db_name [ON CLUSTER cluster]
ENGINE = MySQL('host:port', ['database' | database], 'user', 'password')
clickhouse对应MySQL的数据类型有以下几种:
除了MySQL引擎之外,还支持Hive、MongoDB、SQLite、PostgreSQL、HDFS等等几种数据库引擎。
Clickhouse 中最强大的表引擎当属 MergeTree (合并树)引擎及该系列(*MergeTree
)中的其他引擎。
MergeTree
系列的引擎被设计用于插入极大量的数据到一张表当中。数据可以以数据片段的形式一个接着一个的快速写入,数据片段在后台按照一定的规则进行合并。相比在插入时不断修改(重写)已存储的数据,这种策略会高效很多。
主要特点:
继承MergeTree
引擎,和MergeTree
的不同之处在于它会删除排序键值相同的重复项。
数据的去重只会在数据合并期间进行,合并会在后台一个不确定的时间进行。有一些数据可能仍未被处理。尽管可以调用 OPTIMIZE 语句发起计划外的合并,但 OPTIMIZE
语句会引发对数据的大量读写,不建议使用。
因此,ReplacingMergeTree
适用于在后台清除重复的数据以节省空间,但是它不保证没有重复的数据出现。
项目中的表目前大部分以这种引擎为主,由于更新数据是往数据库插入,故需使用argMax函数去重,才能使用这部分数据,argMax函数使用见第4节。
该引擎继承于MergeTree,并在数据块合并算法中添加了折叠行的逻辑。
CollapsingMergeTree
会异步的删除(折叠)这些除了特定列 Sign
有 1
和 -1
的值以外,其余所有字段的值都相等的成对的行。没有成对的行会被保留。
因此,该引擎可以显著的降低存储量并提高 SELECT
查询效率。
CollapsingMergeTree 参数
1
是«状态»行,-1
是«取消»行。列数据类型 — Int8。该引擎继承自 MergeTree。区别在于,当合并 SummingMergeTree
表的数据片段时,ClickHouse 会把所有具有相同主键的行合并为一行,该行包含了被合并的行中具有数值数据类型的列的汇总值。如果主键的组合方式使得单个键值对应于大量的行,则可以显著的减少存储空间并加快数据查询的速度。
我们推荐将该引擎和 MergeTree
一起使用。例如,在准备做报告的时候,将完整的数据存储在 MergeTree
表中,并且使用 SummingMergeTree
来存储聚合数据。
SummingMergeTree 的参数
如果没有指定 `columns`,ClickHouse 会把所有不在主键中的数值类型的列都进行汇总。
-- 显示当前日期 2022-09-17
select toDate(now())
-- 将字符串转换为日期(注意:这里不能用0.000这种带小数点的秒,不然无法转换)
select toDate('2022-01-01 00:00:00')
-- 将秒级时间戳转换为日期(注意:这里是秒级,不是毫秒级)
select toDate(1663301647)
-- 时间戳
select toDateTime64(1663301647,3)
-- 字符串
select toDateTime64('2022-01-01 00:00:00.000',3)
-- 202209
select toYYYYMM(today())
-- 20220917
select toYYYYMMDD(today())
-- 20220917164457
select toYYYYMMDDhhmmss(now());
visitParamHas(参数,名称)可以判断参数是否存在这个键。
json函数的功能主要是将字符串识别成json,并提取第一个识别到的键的值。
使用聚合函数argMax,argMin可以通过时间取到首次的数据和最后一次更新的数据。
select argMax(id, t.dc_update_time) as id,
receipt_code,
argMax(order_code, t.dc_update_time) as order_code,
argMax(seq_order_no, t.dc_update_time) as seq_order_no,
argMax(source_code, t.dc_update_time) as source_code,
argMax(supplier_code, t.dc_update_time) as supplier_code,
argMax(supplier_name, t.dc_update_time) as supplier_name,
argMax(service_provider_code, t.dc_update_time) as service_provider_code,
argMax(service_provider_name, t.dc_update_time) as service_provider_name,
argMax(certificate, t.dc_update_time) as certificate,
argMax(amount, t.dc_update_time) as amount,
argMax(use_amount, t.dc_update_time) as use_amount,
argMax(state, t.dc_update_time) as state,
argMax(is_deleted, t.dc_update_time) as is_deleted,
argMax(creator_id, t.dc_update_time) as creator_id,
argMax(creator_name, t.dc_update_time) as creator_name,
argMax(created_time, t.dc_update_time) as created_time,
argMax(reviser_id, t.dc_update_time) as reviser_id,
argMax(reviser_name, t.dc_update_time) as reviser_name,
argMax(revised_time, t.dc_update_time) as revised_time,
argMax(dc_update_time, t.dc_update_time) as dc_update_time,
argMax(dc_etl_time, t.dc_update_time) as dc_etl_time
from dwd_acc_deposit_receipt_cp_di t
group by receipt_code
这个sql主要是对receipt_code先进行分组,然后组内对每个数据获取时间的最大值,再取这条数据,这样去重,可以实现每个receipt_code都可以拿到最新的数据。argMin也是相同的用法,可以取到首次的数据。
这里去重也可以使用final关键字(不推荐),根据ReplacingMergeTree引擎的特性,每次合并都会去重数据,final是合并数据达到去重效果,但是会增加IO消耗,不推荐使用。
物化视图是包括一个查询结果的数据库对象,它是远程数据的的本地副本,或者用来生成基于数据表求和的汇总表。物化视图存储基于远程表的数据,简单的来理解就是它在普通视图的基础上加上了视图中select后所存储的数据。
物化视图这些规则已经全部写好并且条件所过滤后的数据已经存储在了本地表中,所以它比原数据查询快了很多。
它是一个流式数据的使用场景,是累加式的技术,所以要用历史数据做去重、去核这样的分析,在物化视图里面是不太好用的。在某些场景的使用也是有限的。而且如果一张表加了好多物化视图,在写这张表的时候,就会消耗很多机器的资源,比如数据带宽占满、存储一下子增加了很多。
CREATE [MATERIALIZED] VIEW [IF NOT EXISTS] [db.]table_name [TO[db.]name] [ENGINE = engine] [POPULATE] AS SELECT …
POPULATE取决于原始表的数据是否导入视图中,若不添加POPULATE关键字则不导入,但官方不推荐这种加POPULATE 的做法,因为我们在同步数据的时候原始表的数据可能存在被插入的情况,这样做会造成数据的丢失。
采集调度任务通过cron表达式完成调度,在上线之后可以按定时按钮操作调度执行。
在项目中海豚调度ods分为三个部分:初始化、补偿、采集,dwd聚合ods(left join)。