Posted by Akilis on 03 Jul, 2024
列式存储、多级索引,查询时根据层层索引找到remark文件,按offset读取磁盘压缩块Block,解压缩再按行offset提取列值。
采用LSM存储思想,可基于SkipList数据结构在内存存储k-v索引值对,使用SSTable在磁盘存储数据,异步合并数据part,支持大数据量并发写入,适合大数据数仓构建。
DDL
```
ENGINE = ReplicatedMergeTree('/clickhouse/ad_dw_hdd/ks_ad_bi/dm_dsp_tfc_effect_creative_pos_aggr_di/{shard}', '{replica}')
PARTITION BY p_date ORDER BY (account_id, campaign_type, product_name, corporation_name, ocpc_action_type)
SETTINGS index_granularity = 8192
```
DistributedMergeTree
数据集预览、ML采样场景,改写引擎查询,使用子查询抽取表时加 Group By
、Sample
、LIMIT
、Order By rand()
限制数据量,避免失败,提升性能,提升均匀性。
近似TopN settings distributed_group_by_no_merge = 1
```
SELECT __time__datetime_1m, _0
FROM
(
SELECT 1710864000000 AS __time__datetime_1m, toString(user_id) AS _0
FROM video2019.live_pull_client_log
WHERE (datetime_1m >= '2024-03-20 00:00:00') AND (datetime_1m <= '2024-03-20 23:59:59')
GROUP BY __time__datetime_1m, _0
ORDER BY __time__datetime_1m ASC, _0 ASC
LIMIT 1000
settings distributed_group_by_no_merge = 1
)
GROUP BY __time__datetime_1m, _0
ORDER BY __time__datetime_1m ASC, _0 ASC
LIMIT 0, 200
```
SAMPLE X
```
SELECT 1700582400000 AS __time__p_date, bundle_id AS _0
FROM
(select *
from ks_radar_plus_public.radar_krn_dwd_load_stat
sample 0.01
WHERE p_date >= '20231122' AND p_date <= '20231128') t
GROUP BY __time__p_date, _0
ORDER BY __time__p_date, _0
LIMIT 200
OFFSET 0
```
LIMIT Y
```
-- LIMIT Y: 40+ rows, 1s
SELECT 1700582400000 AS __time__p_date, bundle_id AS _0
FROM (select * from ks_radar_plus_public.radar_krn_dwd_load_stat WHERE p_date >= '20231122' AND p_date <= '20231128' limit 10000000) t
GROUP BY __time__p_date, _0
ORDER BY __time__p_date, _0
LIMIT 200
OFFSET 0;
```
order by rand() LIMIT Z
```
-- LIMIT Y: 5s
SELECT 1659369600000 AS __time__p_date, query_id AS _0
FROM
(SELECT *
FROM ks_kwaibi.kwaibi_query_metric_cost_detail_daily
WHERE p_date >= '20220802' AND p_date <= '20220809'
AND LOWER(query_id) LIKE LOWER('%kw%')
LIMIT 10000000)
GROUP BY __time__p_date, _0
ORDER BY __time__p_date, _0
LIMIT 200 OFFSET 0
;
-- ORDER BY RAND() LIMIT Z: 5s
SELECT 1659369600000 AS __time__p_date, query_id AS _0
FROM
(SELECT *
FROM ks_kwaibi.kwaibi_query_metric_cost_detail_daily
WHERE p_date >= '20220802' AND p_date <= '20220809'
AND LOWER(query_id) LIKE LOWER('%kw%')
ORDER BY RAND() LIMIT 100000)
GROUP BY __time__p_date, _0
ORDER BY __time__p_date, _0
LIMIT 200 OFFSET 0
;
```
t1 GLOBAL JOIN t2
t1 where c1 GLOBAL IN t2
count(distinct k1)
. 依然有 coordinator sum(cnt_i)
. 可避免 coordinator 去重计算时发生内存瓶颈。多表关联:fact, dim 都使用相同的稳定 sharding key, 然后可在同节点 JOIN 后,执行类似单表的 Local Query.
syntax
```
localQuery(cluster, main table, local query)
cluster:clickhouse集群,即local表所在的集群
main table:分布式表对应的local表,对应的replica merge tree可能会有lag,按这个来选择查询的replica
local query:查询本地的数据,所有的表都需要指定local表
```
demo
```
select p_date
,p_product
,sum(sum1) as sum1
,sum(sum2) as sum2
,sum(sum3) as sum3
FROM localQuery( app_hdd, ks_growth.ck__device__channel_active_device__di_local,
"
select p_date
,p_product
,sum(antispam_active_device_cnt) as sum1
,sum(new_device_cnt) as sum2
,sum(antispam_new_device_cnt) as sum3
from ks_growth.ck__device__channel_active_device__di_local
where p_date >= '20201101' and p_date <= '20201104'
group by p_date, p_product
limit 1000000
"
)
group by p_date, p_product
order by p_date, p_product, sum1
limit 1000000
```
时间累计函数,例如计算“近x小时累计”,“0点截止到当前”,“近x日累计”,“月初截至当日”等可累加指标。
over()
function for Expr & Aggr
syntax
```
-- CH
aggregate_function (column_name)
OVER ([[PARTITION BY grouping_column] [ORDER BY sorting_column]
[ROWS or RANGE expression_to_bound_rows_withing_the_group]] | [window_name])
FROM table_name
WINDOW window_name as ([[PARTITION BY grouping_column] [ORDER BY sorting_column])
-- 开窗 e.g.,
acc(m1) over([partition by window_size] order by p_date window_frame) from subquery
-- subquery 为时间聚合粒度下的分组,普通聚合结果
-- e.g.,
select
dt,
dims,
sum(m1) as m1
from t
where dt >= biggest_granu_start AND dt <= end
group by dt, dims;
```
demo
```
select t.*
-- 累积求和
,sum(normal_sum) over(partition by g_day order by g_hour asc ROWS between unbounded preceding and current row ) as run_tot
from (
WITH cte AS (SELECT 0 as t, 1 as v, 1 AS d -- (g_day, g_hour) = (0, 0)
UNION ALL
SELECT 1, 1, 1 -- (g_day, g_hour) = (0, 0)
UNION ALL
SELECT 1, 1, 0 -- (g_day, g_hour) = (0, 0)
UNION ALL
SELECT 2, 1, 1 -- (g_day, g_hour) = (0, 1)
UNION ALL
SELECT 3, 2, 1 -- (g_day, g_hour) = (0, 1)
UNION ALL
SELECT 4, 4, 1 -- (g_day, g_hour) = (0, 2)
UNION ALL
SELECT 5, 4, 1 -- (g_day, g_hour) = (0, 2)
UNION ALL
SELECT 6, 6, 1 -- (g_day, g_hour) = (1, 3)
UNION ALL
SELECT 7, 7, 0 -- (g_day, g_hour) = (1, 3)
UNION ALL
SELECT 8, null, 1 -- (g_day, g_hour) = (1, 4)
)
select floor(t/6) as g_day,
floor(t/2) as g_hour,
-- 普通求和指标
sum(v) as normal_sum,
from cte
group by g_hour, g_day
) t
order by g_day, g_hour
;
```
嵌套模板编排
[start, end] => [biggest_granu_start, end], biggest_granu_start <= start
select * from res where dt >= start AND dt <= end
累计计算实现方式对比