模型与数仓
DORIS的数据模型很有特色,在意义上针对数仓建设解决了某个问题。数仓的建设思路: 要整合的数据源、要遵从的数据规范,要实现数据指标。 具体到数据指标这一块,必须要对数仓进行分层。
数据分层按照数据加工程度的不同会有以下的划分:
数据贴源层: 从源端复制过来的数据存放到贴源层,最好的贴源层只是数据的移动,其它的没有任何变化,差的贴源层是格式上有变化,而且数据类型和数据长度都有变化,虽然对于业务上来说能够用,但是某些场景用得不太好。
数据明细层: 对源端的数据进行细粒度的加工处理,处理后的数据在业务层面颗粒度是最细的。好的明细层是按域划分的,你可以想像一下,A架摆着一排排花生,B架摆着一层层的芝麻,C架构清一色绿豆,数据有层次、有结构的划分。 差的明细层花生里面混杂着芝麻,芝麻里面有绿豆,分析时需要对材料做过多的筛选。
数据维度层: 时间维度、地理维度、产品维度都是稳定不变的企业根基业务数据,它们的特性是数据少而且唯一,并且随着业务增长不会有太大的变化 。维度层是企业级数据仓库的必不可少的,它们好比柴米油盐的存在。
数据汇聚层:汇聚层的数据已经是粗粒度的状态,数据已经被深度加工,经过重汇、批计的数据可能是按月、按年有目标的形式组织的。举例: 按照菜单需求,1斤花生已泡水半小时,50克芝麻已经成为芝麻碎。
数据服务层:服务层的数据贴近业务应用,组合会更加丰富。 泡水半小时的花生已经和成为芝麻碎的50克花生放在一起发酵2个小时,现在在锅上正待蒸煮。
应用服务层: 应用服务层已经是业务应用,正式服务客户。 凉拌花生芝麻如何快速上桌,满足客户的需求?
DORIS定义表结构支持Aggregate 、Unique 、Duplicate模型,可以满足6个数据分层的需求。
- 数据贴源层只需要一个存放数据的地方,所有的数据库都可以满足。【Duplicate模型】
- 数据明细层需要快速随机查询,并发度高,响应快。【Duplicate模型】
- 数据维度度关注准确性、唯一性。 【Unique模型】
- 数据汇聚层关心数据计算能力,查询语句包括有分组、筛选、过滤等功能。【 Aggregate模型】
- 数据服务层经常干的事情打标签,涉及多表关联,子查询、轻汇。 【Aggregate模型】
- 应用服务层与客户交互 【Duplicate模型】
Aggregate、Unique和Duplicate 的概念如下。
- Aggregate 模型可以通过预聚合,优先聚合查询时所需扫描的数据量和查询的计算量,适合有固定模式的查询类场景。
- Unique 模型针对需要唯一主键约束的场景,可以保证主键唯一性约束,可以保障数据的唯一性。
- Duplicate 适合任意维度的查询,Duplicater模型本身也支持索引、分区、分桶。
除了数据模型,另外DORIS支持MPP,支持向量化,支持高浓度列式,支持高位压缩算法,支持分区分桶提高数据的查询性能。
建模应用
| 字段 | 类型 | 定义 | 聚合?唯一? |
|---|---|---|---|
| user_id | 整数 | 用户id | |
| date | 时间 | 数据灌入日期时间 | |
| timestamp | 时间 | 数据灌入的时间戳 | |
| city | 字符 | 用户所在城市 | |
| age | 整型 | 用户年龄 | |
| sex | 整型 | 用户性别 | |
| last_visit_date | 时间 | 用户最后一次访问时间 | |
| cost | 整型 | 用户总消费 | |
| max_dwell_time | 整型 | 用户最大停留时间 | |
| min_dwell_time | 整型 | 用户最小停留时间 |
根据上面业务需求表,结合具体的SQL查询,哪些字段需要做聚合,哪些字段需要做唯一,哪些需要做索引,哪些做分区,哪些做分桶?
假设业务需要要保留全部的数据,查询会较多的明细查询,单表过滤SQL语句的where过滤较多。建表如下
drop table testdoris.dw_duplicate;
CREATE TABLE IF NOT EXISTS testdoris.dw_duplicate
(
`user_id` LARGEINT NOT NULL COMMENT "用户id",
`date` DATE NOT NULL COMMENT "数据灌入日期时间",
`timestamp` DATETIME NOT NULL COMMENT "数据灌入的时间戳",
`city` VARCHAR(20) COMMENT "用户所在城市",
`age` SMALLINT COMMENT "用户年龄",
`sex` TINYINT COMMENT "用户性别",
`last_visit_date` DATETIME REPLACE DEFAULT "1970-01-01 00:00:00" COMMENT "用户最后一次访问时间",
`cost` BIGINT DEFAULT "0" COMMENT "用户总消费",
`max_dwell_time` INT DEFAULT "0" COMMENT "用户最大停留时间",
`min_dwell_time` INT DEFAULT "99999" COMMENT "用户最小停留时间"
)
ENGINE=olap
DUPLICATE KEY(`user_id`, `date`,`timestamp`,`city`,`sex`)
PARTITION BY RANGE(`date`)
(
PARTITION `p202001` VALUES LESS THAN ("2020-02-01"),
PARTITION `p202002` VALUES LESS THAN ("2020-03-01"),
PARTITION `p202003` VALUES LESS THAN ("2020-04-01")
)
DISTRIBUTED BY HASH(`user_id`) BUCKETS 16
PROPERTIES
(
"replication_num" = "1"
);
假设业务多维查询较多,查询会较多按年月分级分类进行查询,SQL语句涉及的窗口函数、group by较多。针对cost求SUM,max_dwell_time求MAX,min_dwell_time求MIN
drop table testdoris.dw_aggregate;
CREATE TABLE IF NOT EXISTS testdoris.dw_aggregate
(
`user_id` LARGEINT NOT NULL COMMENT "用户id",
`date` DATE NOT NULL COMMENT "数据灌入日期时间",
`timestamp` DATETIME NOT NULL COMMENT "数据灌入的时间戳",
`city` VARCHAR(20) COMMENT "用户所在城市",
`age` SMALLINT COMMENT "用户年龄",
`sex` TINYINT COMMENT "用户性别",
`last_visit_date` DATETIME REPLACE DEFAULT "1970-01-01 00:00:00" COMMENT "用户最后一次访问时间",
`cost` BIGINT SUM DEFAULT "0" COMMENT "用户总消费",
`max_dwell_time` INT MAX DEFAULT "0" COMMENT "用户最大停留时间",
`min_dwell_time` INT MIN DEFAULT "99999" COMMENT "用户最小停留时间"
)
ENGINE=olap
AGGREGATE KEY(`user_id`, `date`, `timestamp`, `city`, `age`, `sex`)
PARTITION BY RANGE(`date`)
(
PARTITION `p202001` VALUES LESS THAN ("2020-02-01"),
PARTITION `p202002` VALUES LESS THAN ("2020-03-01"),
PARTITION `p202003` VALUES LESS THAN ("2020-04-01")
)
DISTRIBUTED BY HASH(`user_id`) BUCKETS 16
PROPERTIES
(
"replication_num" = "1"
);
假如用户数据表的用途很重要,主要用来做主数据系统用途。
drop table testdoris.dw_unique;
CREATE TABLE IF NOT EXISTS testdoris.dw_unique
(
`user_id` LARGEINT NOT NULL COMMENT "用户id",
`date` DATE NOT NULL COMMENT "数据灌入日期时间",
`timestamp` DATETIME NOT NULL COMMENT "数据灌入的时间戳",
`city` VARCHAR(20) COMMENT "用户所在城市",
`age` SMALLINT COMMENT "用户年龄",
`sex` TINYINT COMMENT "用户性别",
`last_visit_date` DATETIME REPLACE DEFAULT "1970-01-01 00:00:00" COMMENT "用户最后一次访问时间",
`cost` BIGINT DEFAULT "0" COMMENT "用户总消费",
`max_dwell_time` INT DEFAULT "0" COMMENT "用户最大停留时间",
`min_dwell_time` INT DEFAULT "99999" COMMENT "用户最小停留时间"
)
ENGINE=olap
UNIQUE KEY(`user_id`,`date`)
PARTITION BY RANGE(`date`)
(
PARTITION `p202001` VALUES LESS THAN ("2020-02-01"),
PARTITION `p202002` VALUES LESS THAN ("2020-03-01"),
PARTITION `p202003` VALUES LESS THAN ("2020-04-01")
)
DISTRIBUTED BY HASH( `user_id`) BUCKETS 16
PROPERTIES
(
"replication_num" = "1"
);
归纳总结
- DORIS的数据模型是从数据加工程度以及粗细粒度定义模型的去定义的,区别于其它数据库。
- 新手接触DORIS,不知道如何选择模型, 可以按duplicate模型去用,DORIS 默认使用的数据模型。记住必需求加分区和分桶,否则性能差异很大,aggregator才是DORIS的数据分析大杀器
- AGGREGATE的相关函数欠缺丰富,以后有待提高。
- 分区分桶设置有可能造成数据分布倾斜,分区分桶要对应CPU个数,参见官方教程。




