文章目录
  1. 非结构化数仓建模和Schema-Less OLAP构建 - TSL(三)
  2. 一、概述
  3. 二、事件分析模型(多维分析)
  4. 三、TSL常见实现方式
    1. 3.1 标准数据集的方式
    2. 3.2 半结构化表模型的方式
    3. 3.3 优化 - 半结构化表模型的方式
    4. 3.4 非结构化表模型的方式
  5. 四、总结

非结构化数仓建模和Schema-Less OLAP构建 - TSL(三)

同步更新:https://icemimosa.notion.site/Schema-Less-OLAP-TSL-6821d3b3bc384a7b8bf43bfbec9b7097

一、概述

在文档 非结构化数仓建模和Schema-Less OLAP构建(零) 我们讲述了如何基于bitmap来作为非结构化建模的底层数据结构,本节我们具体讨论为了构建table schema-less的olap,我们该使用什么样的表结构来存储数据。当然这里只讨论数据的组织方式,不关心具体的OLAP引擎。

二、事件分析模型(多维分析)

在讲解具体的模型结构之前,先解释下什么是「无表结构约束」(schema-less)是一个什么概念,以及实现的常用手段。

在最开始的文章中,我们知道在一条用户行为事件日志中,往往可以抽象拆解成「时间」、「实体」、「维度」、「指标」:

  • 时间:事件发生的时间,往往最后会聚合成分钟、小时、天,当然时间也是一种维度。
  • 实体:分析的实体对象,可以是人、设备、视频、文章、作者等。
  • 维度:事件携带的变量,可以是城市、浏览器、用户属性、事件特有的属性等,由「维度标识」+「维度值」组成。
  • 指标:事件携带的分析指标,可以是事件本身的次数,页面浏览量、停留时长、购买事件的金额等,由「指标标识」+「指标量」组成。

然后将这种模型应用于通用的事件分析工具(多维分析)中,用来解决各种灵活场景的分析,比如:「过去7天」在「城市」维度下,「操作系统: Mac」的人数是多少?

  • 图例:

    http://ice-img.flutterdart.cn/2020-03-22-113238.png

为了解决示例的场景,我们可能需要在hive或者clickhouse中创建如下的表结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
create table tbl (
date string,
city string,
os string,
user_num bigint,
pv bigint,
...
)

-- 或者为了支持用户量(去重类指标)需要创建cube表,或者用户粒度的表
create table tbl (
date string,
user_id string,
city string,
os string,
pv bigint,
...
)

但是这样会出现一些问题,这个往往也是数据开发人员和OLAP引擎开发人员之间比较矛盾的地方:

  • 在图例中,我可能不仅仅会有city、os,可能还会有「APP版本」、「用户属性」、或者某个指标很多特殊的属性,对于已存在的表来说,进行扩展往往显得很脆弱。很多时候为了规避一些不必要的麻烦,我们可能会重新做一张新的表,久而久之,模型数量膨胀也会变成数据治理的难题。
  • 由于「用户量」这种去重类指标,为了满足上卷,我们往往会构建「用户ID」粒度的表,或者构建恶心的cube表。前者在用户数据量大的时候,OLAP引擎往往会显得比较无力;后者就不必多说了,比较难以维护。

那么为了满足上述任意拖拽「维度」+「指标」的分析场景,我们需要引入无表结构约束的概念,无表结构约束并不代表没有表结构,而是引入一些手段来屏蔽底层模型的细节。

三、TSL常见实现方式

基本语义:给予一个定义好的实体模型,可以从中获取任意的维度+指标,所查即所得。

比如简单的语义示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
-- 创建一个实体模型
CREATE MODEL model_name

-- 获取任意的维度、指标
select
_time as date,
city as city,
count(distinct pv) as user_num,
sum(pv) as pv
from model_name
where _time = 100
and os = 'Mac'
group by _time, city

3.1 标准数据集的方式

基于平台工具+数仓星型模型,可以在平台中创建一个标准化的取数数据集,平台只需要维护「维度」+「指标」对应「数仓模型」中字段的绑定关系,这样在分析工具的时候,还原具体的查询语义,找到对应的实际表即可。

这样数据开发人员,业务只需要提供想要满足指标和维度的查询组合需求,开发人员创建对应的hive或者clickhouse表模型,然后绑定到平台即可。对于业务分析来说完全屏蔽了底层查询细节,也可以做到冷热数据的查询分离,底层模型的管理也变得更加的有组织化。当然缺点也很明显:

  • 对于无法满足的指标+维度组合,开发周期较长,还要在平台进行操作绑定
  • 对于热数据OLAP查询,由于星型模型的存在,需要底层引擎支持join的操作
  • 模型只是更加有组织化了,但是时间长了,依然会导致模型数量的膨胀
  • 无法做到真正的所查即所得,对于底层不支持的指标+维度组合,上层是无法做到查询的。

参考:

3.2 半结构化表模型的方式

上述方式仍然没有解决模型过多的问题,那么能不能使用一个模型来满足任意的查询,答案是肯定的。

可以使用json来组织「时间」、「实体」、「维度」、「指标」,这个也是很多埋点流量分析平台的常用实现方式,比如底层表结构如下:

1
2
3
4
5
6
7
create table tbl (
date string, -- 时间
user_id string, -- 实体
dimension json, -- 维度
metric_key string, -- 指标标识
metric_value double -- 指标值
)

这样在实现TSL语义就只需要翻译成对应的sql语句即可,比如翻译成如下SQL:

1
2
3
4
5
6
7
8
9
10
select
date as date,
json(dimension, '$.city') as city,
count(distinct user_id) as user_num,
sum(metric_value) as pv
from tbl
where date = '100'
and json(dimension, '$.os') = 'Mac'
and metric_key = 'pv'
group by date, json(dimension, '$.city')

这样就可以使用一张半结构化的表来实现任意的查询,很明显的缺点就是存储的引擎需要支持ROLAP,并且在查询大用户量的去重类指标的数据时,引擎也会比较吃力吃资源。

3.3 优化 - 半结构化表模型的方式

非结构化数仓建模和Schema-Less OLAP构建 - 优化分层数仓(一) 这篇讲解了如何使用bitmap来削减ROLAP的数据量,这里就不多赘述了。

3.4 非结构化表模型的方式

同样是基于bitmap,使用「指标」+「维度」分离的方式,这样在只查询指标的场景,维度较少的场景,或者存在维度过滤的场景下能够加速查询,因为不需要像ROLAP那样扫描表全部的数据。

参考:非结构化数仓建模和Schema-Less OLAP构建(零)(基于Bitmap的存储模型)

四、总结

在实际场景中,往往一个解决方案其实不能解决所有的场景,目前我个人比较倾向于:

  • 在OLAP模块使用「3.3」+「3.4」结合的方案
  • 「3.2」可以用来满足一些查询明细的场景,比如排查数据问题

当然基于以上的建设方法论,我们也开源了 bitlap 项目,可以用来满足除了多维分析之外更多的分析场景,还请多多关注和支持。

文章目录
  1. 非结构化数仓建模和Schema-Less OLAP构建 - TSL(三)
  2. 一、概述
  3. 二、事件分析模型(多维分析)
  4. 三、TSL常见实现方式
    1. 3.1 标准数据集的方式
    2. 3.2 半结构化表模型的方式
    3. 3.3 优化 - 半结构化表模型的方式
    4. 3.4 非结构化表模型的方式
  5. 四、总结