',20,1,'2017-10-02
12:59:12’,null,200,5,5),\
(10003,‘2017-10-02’,‘广州’,32,0,‘2017-10-02 11:20:00’,'2017-10-02
11:20:00’,30,11,11),\
(10004,‘2017-10-01’,‘深圳’,35,0,‘2017-10-01 10:00:15’,'2017-10-01
10:00:15’,100,3,3),\
(10004,‘2017-10-03’,‘深圳’,35,0,‘2017-10-03 10:20:22’,'2017-10-03
10:20:22’,11,6,6);
注意: Insert into 单条数据这种操作在 Doris 里只能演示不能在生产使用, 会引发写阻 塞。
3)查看表
select \* from test\_db.example\_site\_visit;
可以看到,用户 10000 只剩下了一行聚合后的数据。而其余用户的数据和原始数据保 持一致。经过聚合,Doris 中最终只会存储聚合后的数据。换句话说, 即明细数据会丢失, 用户不能够再查询到聚合前的明细数据了。
#### 3.5.1.2 示例二:保留明细数据
1)建表
CREATE TABLE IF NOT EXISTS test_db.example_site_visit2
(
user_id
LARGEINT NOT NULL COMMENT “用户 id”,
date
DATE NOT NULL COMMENT “数据灌入日期时间”,
timestamp
DATETIME 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 “用户最小停留时
间”
)
AGGREGATE KEY(user_id
, date
, timestamp
, city
, age
, sex
)
DISTRIBUTED BY HASH(user_id
) BUCKETS 10;
2)插入数据
insert into test_db.example_site_visit2 values(10000,‘2017-10-
01’,‘2017-10-01 08:00:05’,’ 北 京 ',20,0,‘2017-10-01
06:00:00’,20,10,10),
(10000,‘2017-10-01’,‘2017-10-01 09:00:05’,‘北京’,20,0,‘2017-10-01
07:00:00’,15,2,2),
(10001,‘2017-10-01’,‘2017-10-01 18:12:10’,‘北京’,30,1,‘2017-10-01
17:05:45’,2,22,22),
(10002,‘2017-10-02’,‘2017-10-02 13:10:00’,‘上海’,20,1,‘2017-10-02
12:59:12’,200,5,5),
(10003,‘2017-10-02’,‘2017-10-02 13:15:00’,‘广州’,32,0,‘2017-10-02
11:20:00’,30,11,11),
(10004,‘2017-10-01’,‘2017-10-01 12:12:48’,‘深圳’,35,0,‘2017-10-01
10:00:15’,100,3,3),
(10004,‘2017-10-03’,‘2017-10-03 12:38:20’,‘深圳’,35,0,‘2017-10-03
10:20:22’,11,6,6);
3)查看表
select * from test_db.example_site_visit2;
存储的数据,和导入数据完全一样, 没有发生任何聚合。这是因为,这批数据中, 因为 加入了 timestamp 列,所有行的 Key 都不完全相同。也就是说,只要保证导入的数据中,
每一行的 Key 都不完全相同,那么即使在聚合模型下,Doris 也可以保存完整的明细数据。
#### 3.5.1.3 示例三:导入数据与已有数据聚合
1)往实例一中继续插入数据
insert into test_db.example_site_visit values(10004,‘2017-10-03’,’
深圳’,35,0,‘2017-10-03 11:22:00’,null,44,19,19),
(10005,‘2017-10-03’,‘长沙’,29,1,‘2017-10-03 18:11:02’,‘2017-10-03
18:11:02’,3,1,1);
2)查看表
select * from test_db.example_site_visit;
可以看到,用户 10004 的已有数据和新导入的数据发生了聚合。同时新增了 10005 用 户的数据。
3.5.2 Uniq 模型
在某些多维分析场景下,用户更关注的是如何保证 Key 的唯一性,即如何获得 Primary Key 唯一性约束。因此,我们引入了 Uniq 的数据模型。该模型本质上是聚合模型的一个特 例,也是一种简化的表结构表示方式。
1)建表
CREATE TABLE IF NOT EXISTS test_db.user
(
user_id
LARGEINT NOT NULL COMMENT “用户 id”,
username
VARCHAR(50) NOT NULL COMMENT “用户昵称”,
city
VARCHAR(20) COMMENT “用户所在城市”,
age
SMALLINT COMMENT “用户年龄”,
sex
TINYINT COMMENT “用户性别”,
phone
LARGEINT COMMENT “用户电话”,
address
VARCHAR(500) COMMENT “用户地址”,
register_time
DATETIME COMMENT “用户注册时间”
)
UNIQUE KEY(user_id
, username
)
DISTRIBUTED BY HASH(user_id
) BUCKETS 10;
2)插入数据
insert into test_db.user values
(10000,‘wuyanzu’,’ 北 京 ‘,18,0,12345678910,’ 北 京 朝 阳 区 ‘,‘2017-10-01
07:00:00’),
(10000,‘wuyanzu’,’ 北 京 ‘,19,0,12345678910,’ 北 京 朝 阳 区 ',‘2017-10-01
07:00:00’),
(10000,‘zhangsan’,‘北京’,20,0,12345678910,‘北京海淀区’,‘2017-11-15
06:10:20’);
3)查询表
select * from test_db.user;
Uniq 模型完全可以用聚合模型中的 REPLACE 方式替代。其内部的实现方式和数据存 储方式也完全一样。
3.5.3 Duplicate 模型
在某些多维分析场景下,数据既没有主键,也没有聚合需求。 Duplicate 数据模型可以 满足这类需求。数据完全按照导入文件中的数据进行存储,不会有任何聚合。即使两行数据 完全相同, 也都会保留。 而在建表语句中指定的 DUPLICATE KEY,只是用来指明底层数 据按照那些列进行排序。
1)建表
CREATE TABLE IF NOT EXISTS test_db.example_log
(
timestamp
DATETIME NOT NULL COMMENT “日志时间”,
type
INT NOT NULL COMMENT “日志类型”,
error_code
INT COMMENT “错误码”,
error_msg
VARCHAR(1024) COMMENT “错误详细信息”,
op_id
BIGINT COMMENT “负责人 id”,
op_time
DATETIME COMMENT “处理时间”
)
DUPLICATE KEY(timestamp
, type
)
DISTRIBUTED BY HASH(timestamp
) BUCKETS 10;
2)插入数据
insert into test_db.example_log values
(‘2017-10-01 08:00:05’,1,404,‘not found page’, 101, ‘2017-10-01
08:00:05’),
(‘2017-10-01 08:00:05’,1,404,‘not found page’, 101, ‘2017-10-01
08:00:05’),
(‘2017-10-01 08:00:05’,2,404,‘not found page’, 101, ‘2017-10-01
08:00:06’),
(‘2017-10-01 08:00:06’,2,404,‘not found page’, 101, ‘2017-10-01
08:00:07’);
3)查看表
select * from test_db.example_log;
#### 3.5.4 数据模型的选择建议
因为数据模型在建表时就已经确定, 且无法修改。所以, 选择一个合适的数据模型非常 重要。
(1) Aggregate 模型可以通过预聚合,极大地降低聚合查询时所需扫描的数据量和查询 的计算量,非常适合有固定模式的报表类查询场景。但是该模型对 count(\*) 查询很不友好。 同时因为固定了 Value 列上的聚合方式, 在进行其他类型的聚合查询时,需要考虑语意正确 性。
(2) Uniq 模型针对需要唯一主键约束的场景, 可以保证主键唯一性约束。但是无法利 用 ROLLUP 等预聚合带来的查询优势(因为本质是REPLACE,没有 SUM 这种聚合方式)。
(3) Duplicate 适合任意维度的 Ad-hoc 查询。虽然同样无法利用预聚合的特性,但是不 受聚合模型的约束,可以发挥列存模型的优势(只读取相关列,而不需要读取所有 Key 列)
3.5.5 聚合模型的局限性
这里我们针对 Aggregate 模型(包括 Uniq 模型), 来介绍下聚合模型的局限性。
在聚合模型中, 模型对外展现的,是最终聚合后的数据。也就是说,任何还未聚合的数 据(比如说两个不同导入批次的数据) ,必须通过某种方式, 以保证对外展示的一致性。我 们举例说明。
假设表结构如下:
| ColumnName | Type | AggregationType | Comment |
| --- | --- | --- | --- |
| user\_id | LARGEINT | | 用户 id |
| date | DATE | | 数据灌入日期 |
| cost | BIGINT | SUM | 用户总消费 |
假设存储引擎中有如下两个已经导入完成的批次的数据:
batch 1
| user\_id | date | cost |
| --- | --- | --- |
| 10001 | 2017- 11-20 | 50 |
| 10002 | 2017- 11-21 | 39 |
batch 2
| user\_id | date | cost |
| --- | --- | --- |
| 10001 | 2017- 11-20 | 1 |
| 10001 | 2017- 11-21 | 5 |
| 10003 | 2017- 11-22 | 22 |
可以看到,用户 10001 分属在两个导入批次中的数据还没有聚合。但是为了保证用户
只能查询到如下最终聚合后的数据:
| user\_id | date | cost |
| --- | --- | --- |
| 10001 | 2017- 11-20 | 51 |
| 10001 | 2017- 11-21 | 5 |
| 10002 | 2017- 11-21 | 39 |
| 10003 | 2017- 11-22 | 22 |
在查询引擎中加入了聚合算子, 来保证数据对外的一致性。
![img](https://img-blog.csdnimg.cn/img_convert/3190612f69aca0ced82f1768ed3cb8f9.png)
![img](https://img-blog.csdnimg.cn/img_convert/b2228f46bae8b61d322872d1eae3f0f6.png)
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
转存中...(img-d4pNhg4U-1714788184797)]
[外链图片转存中...(img-22L5veD0-1714788184798)]
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**