【大数据系列】二、Doris数据模型详解

打印 上一主题 下一主题

主题 916|帖子 916|积分 2748

Doris数据模型先容

1.模型概述

​ 在 Doris 中,数据以表(Table)的形式进行逻辑上的形貌。一张表包罗行(Row)和列(Column)。Row 即用户的一行数据,Column 用于形貌一行数据中差别的字段。
​ Column 可以分为两大类:Key 和 Value。从业务角度看,Key 和 Value 可以分别对应维度列和指标列。Doris 的 Key 列是建表语句中指定的列,建表语句中的关键字 unique key 或 aggregate key 或 duplicate key 背面的列就是 Key 列,除了 Key 列剩下的就是 Value 列。
​ Doris 的数据模型分为 3 类:


  • 明细模型(Duplicate Key Model):允许指定的 Key 列重复,Doirs 存储层保留所有写入的数据,实用于必须保留所有原始数据记录的情况。
  • 主键模型(Unique Key Model):每一行的 Key 值唯一,可确保给定的 Key 列不会存在重复行,Doris 存储层对每个 key 只保留最新写入的数据,实用于数据更新的情况。
  • 聚合模型(Aggregate Key Model):可根据 Key 列聚合数据,Doris 存储层保留聚合后的数据,从而可以淘汰存储空间和提拔查询性能;通常用于需要汇总或聚合信息(如总数或平均值)的情况。
2.明细模型

使用场景:必须保留所有原始数据记录,针对这种需求,可以使用明细数据模型
​ 在明细数据模型中,存储层会保留写入的所有数据。纵然两行数据完全相同,也都会保留。建表语句中指定的 Duplicate Key,只是用来指明数据存储按照哪些列进行排序,可以用于优化常用查询。
1.创建表
  1. create table test.students
  2. (
  3. sid int comment '学生id',
  4. sname varchar(128) comment '学生姓名',
  5. saddress varchar(100) not null comment '地址',
  6. sxk varchar(100) comment '学科',
  7. fs double comment '分数'
  8. )
  9. engine=olap
  10. DUPLICATE KEY(sid)
  11. PARTITION BY LIST(saddress)
  12. (
  13. PARTITION cq VALUES IN ("重庆"),
  14. PARTITION bj VALUES IN ("北京"),
  15. PARTITION cd VALUES IN ("成都")
  16. )
  17. DISTRIBUTED BY HASH(sid) BUCKETS 5
复制代码
建表说明:
1、ENGINE 的类型是 olap,即默认的 ENGINE 类型。在 Doris 中,只有这个ENGINE 类型是由 Doris 负责数据管理和存储的。其他 ENGINE 类型,如 mysql、broker、es 等等,本质上只是对外部其他数据库或系统中的表的映射,以保证 Doris 可以读取这些数据。而 Doris 自己并不创建、管理和存储任何非 olap ENGINE 类型的表和数据。
2、DUPLICATE KEY 说明是一个明细模型,也叫做冗余模型
3、PARTITION BY LIST 指定列表分区,根据某个字段,设置对应的列表
4、DISTRIBUTED BY HASH(sid) BUCKETS 5 ,设置分桶规则。必须
2.添加数据
  1. insert into test.students values(1,'zhangsan','重庆','语文',98.5);
  2. insert into test.students values(2,'lisi','成都','语文',98.5);
  3. insert into test.students values(3,'wangwu','北京','语文',98.5);
  4. #查询
  5. mysql> select * from test.students;
  6. +------+----------+----------+--------+------+
  7. | sid  | sname    | saddress | sxk    | fs   |
  8. +------+----------+----------+--------+------+
  9. |    2 | lisi     | 成都     | 语文   | 98.5 |
  10. |    3 | wangwu   | 北京     | 语文   | 98.5 |
  11. |    1 | zhangsan | 重庆     | 语文   | 98.5 |
  12. +------+----------+----------+--------+------+
  13. 3 rows in set (0.10 sec)
复制代码
3.添加重复数据
  1. mysql> insert into test.students values(1,'zhangsan','重庆','语文',98.5);
  2. Query OK, 1 row affected (0.14 sec)
  3. {'label':'insert_9d8697a41b64437_b8314e8794094798', 'status':'VISIBLE', 'txnId':'5007'}
  4. mysql> select * from test.students;
  5. +------+----------+----------+--------+------+
  6. | sid  | sname    | saddress | sxk    | fs   |
  7. +------+----------+----------+--------+------+
  8. |    2 | lisi     | 成都     | 语文   | 98.5 |
  9. |    1 | zhangsan | 重庆     | 语文   | 98.5 |
  10. |    1 | zhangsan | 重庆     | 语文   | 98.5 |
  11. |    3 | wangwu   | 北京     | 语文   | 98.5 |
  12. +------+----------+----------+--------+------+
  13. 4 rows in set (0.07 sec)
  14. mysql>
复制代码
4.更新数据
  1. mysql> update test.students set fs=100 where sid=3;
  2. ERROR 1105 (HY000): errCode = 2, detailMessage = Only unique table could be updated.
复制代码
可以看到更新数据失败,提示只有主键模型支持更新数据。
5.删除数据
doris删除数据时,如果没有指定分区,需要设置会话参数
set delete_without_partition = true;
  1. mysql> select * from students;
  2. +------+------------+----------+--------+------+
  3. | sid  | sname      | saddress | sxk    | fs   |
  4. +------+------------+----------+--------+------+
  5. |    2 | lisi       | 成都     | 语文   | 98.5 |
  6. |    1 | zhangsan   | 重庆     | 语文   | 98.5 |
  7. |    1 | zhangsan   | 重庆     | 语文   | 98.5 |
  8. |    4 | zhangliang | 北京     | 数学   | 98.5 |
  9. |    3 | wangwu     | 北京     | 语文   | 98.5 |
  10. +------+------------+----------+--------+------+
  11. 5 rows in set (0.13 sec)
  12. mysql> delete from students where sid=4;
  13. ERROR 1105 (HY000): errCode = 2, detailMessage = errCode = 2, detailMessage = This is a range or list partitioned table. You should specify partition in delete stmt, or set delete_without_partition to true
  14. mysql> set delete_without_partition = true
  15.     -> ;
  16. Query OK, 0 rows affected (0.02 sec)
  17. mysql> delete from students where sid=4;
  18. Query OK, 0 rows affected (0.13 sec)
  19. {'label':'delete_65d452e0-0c0d-438a-a011-c98243b9454d', 'status':'VISIBLE', 'txnId':'5010'}
  20. mysql>
复制代码
如何指定分区,可以直接删除
  1. mysql> delete from students partition bj  where sid=3;
  2. Query OK, 0 rows affected (0.07 sec)
  3. {'label':'delete_03c0808a-3efc-465f-ba84-e7e3502cc7f8', 'status':'VISIBLE', 'txnId':'5056'}
  4. mysql>
复制代码
doris如何检察分区?
  1. mysql> show partitions from students \G;
  2. *************************** 1. row ***************************
  3.              PartitionId: 15004
  4.            PartitionName: bj
  5.           VisibleVersion: 5
  6.       VisibleVersionTime: 2024-12-03 20:35:15
  7.                    State: NORMAL
  8.             PartitionKey: saddress
  9.                    Range: [types: [VARCHAR]; keys: [北京]; ]
  10.          DistributionKey: sid
  11.                  Buckets: 5
  12.           ReplicationNum: 3
  13.            StorageMedium: HDD
  14.             CooldownTime: 9999-12-31 23:59:59
  15.      RemoteStoragePolicy:
  16. LastConsistencyCheckTime: NULL
  17.                 DataSize: 6.182 KB
  18.               IsInMemory: false
  19.        ReplicaAllocation: tag.location.default: 3
  20.                IsMutable: true
  21. *************************** 2. row ***************************
  22.              PartitionId: 15005
  23.            PartitionName: cd
  24.           VisibleVersion: 3
  25.       VisibleVersionTime: 2024-12-03 20:28:43
  26.                    State: NORMAL
  27.             PartitionKey: saddress
  28.                    Range: [types: [VARCHAR]; keys: [成都]; ]
  29.          DistributionKey: sid
  30.                  Buckets: 5
  31.           ReplicationNum: 3
  32.            StorageMedium: HDD
  33.             CooldownTime: 9999-12-31 23:59:59
  34.      RemoteStoragePolicy:
  35. LastConsistencyCheckTime: NULL
  36.                 DataSize: 3.056 KB
  37.               IsInMemory: false
  38.        ReplicaAllocation: tag.location.default: 3
  39.                IsMutable: true
  40. *************************** 3. row ***************************
  41.              PartitionId: 15003
  42.            PartitionName: cq
  43.           VisibleVersion: 4
  44.       VisibleVersionTime: 2024-12-03 20:28:43
  45.                    State: NORMAL
  46.             PartitionKey: saddress
  47.                    Range: [types: [VARCHAR]; keys: [重庆]; ]
  48.          DistributionKey: sid
  49.                  Buckets: 5
  50.           ReplicationNum: 3
  51.            StorageMedium: HDD
  52.             CooldownTime: 9999-12-31 23:59:59
  53.      RemoteStoragePolicy:
  54. LastConsistencyCheckTime: NULL
  55.                 DataSize: 5.146 KB
  56.               IsInMemory: false
  57.        ReplicaAllocation: tag.location.default: 3
  58.                IsMutable: true
  59. 3 rows in set (0.00 sec)
复制代码
总结:


  • 明细模型无法修改数据
  • 删除数据时,如果不指定分区需要设置参数delete_without_partition
  • 当创建表的时间没有指定 Unique、Aggregate 或 Duplicate 时,会默认创建一个 Duplicate 模型的表并且排序建默认选定前面字段
  1. mysql> create table test.students_test
  2.     -> (
  3.     -> sid int comment '学生id',
  4.     -> sname varchar(128) comment '学生姓名',
  5.     -> saddress varchar(100) not null comment '地址',
  6.     -> sxk varchar(100) comment '学科',
  7.     -> fs double comment '分数'
  8.     -> )
  9.     -> engine=olap
  10.     -> PARTITION BY LIST(saddress)
  11.     -> (
  12.     -> PARTITION cq VALUES IN ("重庆"),
  13.     -> PARTITION bj VALUES IN ("北京"),
  14.     -> PARTITION cd VALUES IN ("成都")
  15.     -> )
  16.     -> DISTRIBUTED BY HASH(sid) BUCKETS 5 ;
  17. Query OK, 0 rows affected (0.11 sec)
  18. mysql> desc test.students_test;
  19. +----------+--------------+------+-------+---------+-------+
  20. | Field    | Type         | Null | Key   | Default | Extra |
  21. +----------+--------------+------+-------+---------+-------+
  22. | sid      | INT          | Yes  | true  | NULL    |       |
  23. | sname    | VARCHAR(128) | Yes  | true  | NULL    |       |
  24. | saddress | VARCHAR(100) | No   | false | NULL    | NONE  |
  25. | sxk      | VARCHAR(100) | Yes  | false | NULL    | NONE  |
  26. | fs       | DOUBLE       | Yes  | false | NULL    | NONE  |
  27. +----------+--------------+------+-------+---------+-------+
  28. 5 rows in set (0.02 sec)
复制代码
3.主键模型

​ 由于明细模型无法对数据进行更新操作,那么就引出主键模型,当用户有数据更新需求时,可以选择使用主键数据模型(Unique)。主键模型能够保证 Key(主键)的唯一性,当用户更新一条数据时,新写入的数据会覆盖具有相同 key(主键)的旧数据。
主键模型有两种实现方式:


  • 写时合并 (merge-on-write)。该实现会在数据写入阶段完成所有数据去重的工作,因此能够提供非常好的查询性能。,由于其良好的查询性能,写时合并成为 Unique 模型的默认实现。
  • 读时合并。在读时合并实现中,用户在进行数据写入时不会触发任何数据去重相关的操作,所有数据去重的操作都在查询或者compaction 时进行。因此,读时合并的写入性能较好,查询性能较差,同时内存消耗也较高。
1.创建主键模型表
写时合并
  1. create table test.users
  2. (id int comment '唯一标识',
  3. name string comment '名称',
  4. address string not null comment '地址')
  5. engine=olap
  6. UNIQUE KEY (id)
  7. DISTRIBUTED BY HASH(id) BUCKETS 5;
复制代码
读时合并
  1. create table test.users
  2. (id int comment '唯一标识',
  3. name string comment '名称',
  4. address string not null comment '地址')
  5. engine=olap
  6. UNIQUE KEY (id)
  7. DISTRIBUTED BY HASH(id) BUCKETS 5;
  8. PROPERTIES ("enable_unique_key_merge_on_write" = "false");
复制代码
默认创建主键表是写时合并模式
2.插入数据
  1. mysql> insert into test.users values(1,'zhnagsan','北京');                                                                                                      Query OK, 1 row affected (0.14 sec)
  2. {'label':'insert_83e627ca685c4cb7_a3bf52a25753f6f8', 'status':'VISIBLE', 'txnId':'5072'}
  3. mysql> insert into test.users values(2,'lisi','重庆');
  4. Query OK, 1 row affected (0.22 sec)
  5. {'label':'insert_2f34e1c815314597_996f9c249ea68088', 'status':'VISIBLE', 'txnId':'5073'}
  6. mysql> select * from test.users;
  7. +------+----------+---------+
  8. | id   | name     | address |
  9. +------+----------+---------+
  10. |    2 | lisi     | 重庆    |
  11. |    1 | zhnagsan | 北京    |
  12. +------+----------+---------+
  13. 2 rows in set (0.67 sec)
复制代码
3.修改数据
a.通过insert的方式修改
  1. mysql> insert into test.users values(2,'wangwu','成都');
  2. Query OK, 1 row affected (0.10 sec)
  3. {'label':'insert_522a63ad0a894a2c_92ba6baebdb9b570', 'status':'VISIBLE', 'txnId':'5074'}
  4. mysql> select * from test.users;
  5. +------+----------+---------+
  6. | id   | name     | address |
  7. +------+----------+---------+
  8. |    2 | wangwu   | 成都    |
  9. |    1 | zhnagsan | 北京    |
  10. +------+----------+---------+
  11. 2 rows in set (0.13 sec)
复制代码
可以看到主键模型是通过**UPSERT**数据更新语义执行的,insert时,如果key存在则修改,不存在则插入。
b.通过update的方式进行修改
  1. mysql> select * from test.users;
  2. +------+----------+---------+
  3. | id   | name     | address |
  4. +------+----------+---------+
  5. |    2 | wangwu   | 成都    |
  6. |    1 | zhnagsan | 北京    |
  7. +------+----------+---------+
  8. 2 rows in set (0.13 sec)
  9. mysql> update test.users set name='lllll' where id=2;
  10. Query OK, 1 row affected (0.08 sec)
  11. {'label':'update_8c55594748314b1e_b4314d727736fe37', 'status':'VISIBLE', 'txnId':'5076'}
  12. mysql> select * from test.users;
  13. +------+----------+---------+
  14. | id   | name     | address |
  15. +------+----------+---------+
  16. |    2 | lllll    | 成都    |
  17. |    1 | zhnagsan | 北京    |
  18. +------+----------+---------+
  19. 2 rows in set (0.04 sec)
  20. mysql>
复制代码
可以采用 Update 语句来进行更新,这种 Update 语句一样平常采用先将整行数据读出,然后再更新部分字段值,再写回。这种读写事务非常耗时,并且不适合大批量数据写入
4.删除数据
删除数据与常规语法一致。
  1. mysql> select * from test.users;
  2. +------+----------+---------+
  3. | id   | name     | address |
  4. +------+----------+---------+
  5. |    1 | zhnagsan | 北京    |
  6. |    2 | lllll    | 成都    |
  7. +------+----------+---------+
  8. 2 rows in set (0.03 sec)
  9. mysql> delete from test.users where id=2;
  10. Query OK, 0 rows affected (0.05 sec)
  11. {'label':'delete_7be02826-0c23-4417-ad06-cca3d9e513db', 'status':'VISIBLE', 'txnId':'5077'}
  12. mysql> select * from test.users;
  13. +------+----------+---------+
  14. | id   | name     | address |
  15. +------+----------+---------+
  16. |    1 | zhnagsan | 北京    |
  17. +------+----------+---------+
  18. 1 row in set (0.15 sec)
  19. mysql>
复制代码
后续持续更新…

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

我可以不吃啊

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表