Doris 模型使用说明
Doris 三种模型的使用场景、方法说明。
模型 | 关键字 | 特点 |
---|---|---|
明细模型 | DUPLICATE KEY | 默认模型 |
聚合模型 | AGGREGATE KEY | 按照 AGGREGATE KEY 指定的字段和 表中定义了的聚合字段进行聚合 |
更新模型 | UNIQUE KEY | 按照 AGGREGATE KEY 指定的字段判断是否重复,如果重复则覆盖更新 |
明细模型
适用场景
Doris 建表的默认模型是明细模型。
一般用明细模型来处理的场景有如下特点:
1 | 1.需要保留最原始的数据(如,原始日志,原始操作记录等)来进行分析; |
模型原理
Doris 会为明细模型的表维护排序列,表中的数据会按照排序列进行排序存储。
排序列可以是一列,也可以由多列构成。排序列可以由用户指定,如果用户没有明确指定,那么 Doris 会为表选择默认的几个列作为排序列。
这样,在查询中,如果有相关排序列的过滤条件时,Doris 能够 快速地过滤数据,降低整个查询的时延。
使用案例
创建表的默认数据模型就是明细模型,在向 Doris 明细模型表中导入完全相同的两行数据时,Doris会认为是两行数据。
因为在使用过程中,用户经常会用到时间以及事件类型作为过滤条件,所以将这两个列放在建表的前两 列(事件时间和事件类型)作为排序列。以下是一个使用明细模型创建数据表的例子:
建表
1 | drop table if exists demo_model_detail; |
插入数据
1 | insert into demo_model_detail values |
查询
1 | select * from demo_model_detail; |
Tips
充分利用排序列,在建表时将经常在查询中用于过滤的列放在表的前面,这样能够提升查询速度。
聚合模型
适用场景
在数据分析领域中,有很多场景需要对数据进行统计和汇总操作。
例如:
在网站、APP分析中对访问流量进行分析,获得用户的访问时长总计、访问次数总计等统计;
广告厂商为广告主提供的广告 点击总量、展示总量、消费统计等。
上述的场景就比较适合使用聚合模型来进行查询加速,以下是一些适合聚合模型的场景:
1 | 1.业务方进行的查询都是汇总类查询,比如sum、count等类型的查询; |
模型原理
Doris 会将指标按照相同维度进行聚合。当多条数据具有相同的维度时,Doris会把指标进行聚合。
从而能够减少查询时所需要的处理的数据量,提升查询的效率。
以下面的原始数据为例:
date | Country | PV |
---|---|---|
2021-04-10 | CHN | 1 |
2021-04-10 | CHN | 2 |
2021-04-10 | USA | 3 |
2021-04-10 | USA | 4 |
在 Doris 聚合模型的表中,存储内容会从四条数据变为两条数据。
这样在后续查询处理的时候,处理的数据量就会有指数级的下降。
date | Country | PV |
---|---|---|
2021-04-10 | CHN | 3 |
2021-04-10 | USA | 7 |
使用案例
在建表时,为需要进行聚合的列分配对应的聚合操作就能够使用聚合模型。
以下是一个使用聚合模型创建数据表的例子:
建表
1 | drop table if exists example_db.demo_model_aggregate; |
插入数据
1 | insert into demo_model_aggregate |
查询
1 | select * from demo_model_aggregate; |
Tips
1.对于聚合列上的过滤条件,Doris 并不能够直接对于扫描出来的单行数据进行过滤。
Doris 会将所有 Key 列(指的是上面的 date, country 两个列,他们没有被定义为聚合列)数据以及相应的聚合列数据全部读取出来。
然后将 Key 列相同的不同版本数据进行合并计算出对应的聚合列内容。最后再对计算出的最终聚合列内容进行条件过滤。
所以聚合列上的过滤会比 Key 列上的查询速度慢。这里可以进行优化,如果这个列没有聚合的操作,那么可以将这个列创建为 Key 列。
2.聚合模型目前支持的聚合函数有SUM, MIN, MAX, REPLACE。
更新模型
适用场景
在有些分析场景中,分析的数据经常会发生改变。对于这些分析场景的需求,可以使用 Doris 的更新模型来实现。
比如在电商场景中,定单的状态经常会发生变化,而且变化量又比较大,大型电商公司,每天的订单更新量可能上亿。
要在这种量级的更新场景下进行实时数据分析,如果在明细模型下通过 delete + insert 的方式,是无法满足这么频繁的更新需求的。
这种场景下,用户需要使用更来满足数据分析需求。
以下是一些适合更新模型的场景:
1 | 1.已经写入的数据有大量的更新需求; |
模型原理
Doris 存储内部会给每一个批次导入数据分配一个版本号,在查询的时候对于主键相同的两条数据,
版本大的数据(也就是更新的数据)被返回,而版本较小的数据不会被返回。
ID | value | __version |
---|---|---|
1 | 100 | 1 |
1 | 101 | 2 |
2 | 100 | 3 |
2 | 101 | 4 |
2 | 102 | 5 |
具体的示例如上表所示,ID是表的主键,value是表的内容,而 __version 是 Doris 内部的版本号。
其中 ID为1的数据有两个导入批次,版本分别为1,2;
ID 为 2 的数据有三个批次导入,版本分别为 3,4,5。
在查询的时候对于 ID 为 1 只会返回最新版本 2 的数据,而对于 ID 为 2 只会返回最新版本 5 的数据,
那么对于用户能能够看到的数据如下表所示:
ID | value |
---|---|
1 | 100 |
2 | 102 |
通过这种机制,Doris可以支持对于频繁更新数据的分析。
使用案例
例如在订单分析场景中,经常会有根据订单状态进行的统计分析需求。
因为订单状态经常改变,而 create_time 和order_id 不会改变,并且经常会在查询中作为过滤条件。
所以可以将 create_time 和 order_id 两个列作为这个表的主键(即:在建表时用 UNIQUE KEY 关键字定义),
这样既能够满足订单状态的更新需求,又能够在查询中进行快速过滤。
以下是一个使用更新模型创建数据表的例子:
建表
1 | drop table if exists example_db.demo_model_update; |
插入数据
1 | insert into example_db.demo_model_update |
查询
1 | select * from example_db.demo_model_update; |
Tips
1.导入数据时需要将所有字段补全才能够完成更新操作,
如上述例子中的 create_time、order_id、order_state 和 total_price 四个字段都需必须存在。
2.对于更新模型的数据读取,需要在查询时完成多版本合并,当版本过多时会导致查询性能降低。
所以在向更新模型导入数据时,应该适当降低导入频率,从而提升查询性能。
建议在设计导入频率时以满足业务对实时性的要求为准。如果业务对实时性的要求是分钟级别,那么每分钟导入一次更新数据即可,不需要秒级导入。
3.在查询时,对于 value 字段的过滤通常在多版本合并之后。
可以将经常过滤字段且不会被修改的字段放在主键上。这样能够在合并之前就将数据过滤掉,从而提升查询性能。
4.因为合并过程需要将所有主键字段进行比较,所以应该避免放置过多的主键字段,以免降低查询能。
如果某个字段只是偶尔会作为查询中的过滤条件存在,不需要放在主键中。