Sequence-Column
UNIQUE KEY 模型下,PALO 会根据主键自动的进行数据的更新。但是当同一批次导入数据中出现相同主键的行时,PALO 无法判断其先后顺序,则可能出现更新行为不一致的问题。
而在某些数据同步场景下,需要保证数据能够按顺序更新,而 Sequence Column 功能就是为了解决这一问题。
实现原理
Sequence Column 仅支持 UNQIUE KEY 模型的表。其原理是在表中增加一个隐藏列 __DORIS_SEQUENCE_COL__ 。该列的类型由用户在建表时指定。
在导入的源数据中,用户需额外增加一个顺序列,其类型为建表时指定的 __DORIS_SEQUENCE_COL__ 的类型。PALO 内部会根据这个顺序列的值,决定数据的前后顺序,进行数据更新。
启用 Sequence Column 功能
该功能是 PALO 3.10 版本之后引入的新功能。
-
创建新表
在创建表时,我们可以通过如下方式设置 Sequence Column:
SQL1CREATE TABLE order_table 2( 3 order_id BIGINT, 4 order_type VARCHAR(8), 5 order_status VARCHAR(32) 6) 7UNIQUE KEY(order_id) 8DISTRIBUTED BY HASH(order_id) BUCKETS 8 9PROPERTIES 10( 11 "function_column.sequence_type" = 'Date' 12);这里我们在
PROPERTIES中指定了 Sequence Column 的类型为 Date,即开启了该功能。更多说明,可参阅 CREATE TABLE 命令手册。 -
为旧表开启该功能
对于 3.10 之前版本创建的 UNIQUE KEY 的表,可以通过以下命令开启该功能:
SQL1ALTER TABLE order_table ENABLE FEATURE "SEQUENCE_LOAD" 2WITH PROPERTIES ("function_column.sequence_type" = "Date")这个操作本质上是一个 Schema Change 操作,执行后,需通过 SHOW ALTER TABLE COLUMN 查看作业执行进度。
如果想确定一个表是否已开启标记删除功能,可以通过 设置一个变量来显示隐藏列
1SET show_hidden_columns=true`
之后使用 DESC tablename,如果输出中有 __DORIS_SEQUENCE_COL__ 列,则表示该表已开启该功能。
在导入中使用顺序列功能
在不同的数据导入方式中使用的方式略有不同。该功能目前支持以下数据导入方式:
具体使用语法请参阅各自的文档,这里仅对不同导入方式进行简单的示例说明。假设原始导入数据如下:
11000,TYPE#1,PENDING,2020-10-01
21001,TYPE#2,PAID,2020-10-02
31002,TYPE#3,PENDING,2020-10-03
41001,TYPE#2,PENDING,2020-10-01
51004,TYPE#3,PAID,2020-10-03
Stream Load
1curl --location-trusted -u root \
2-H "columns: order_id, order_type, order_status, source_sequence"
3-H "function_column.sequence_col: source_sequence" \
4-T data.txt http://host:port/api/example_db/order/_stream_load
我们在 Header 的 columns 属性中将第四列命名为 source_sequence,之后在 function_column.sequence_col 属性中将该列设置的顺序列。
这样,源数据中的 1001 这个订单的最终状态将会是 PAID.
Broker Load
1LOAD LABEL example_db.label1
2(
3 DATA INFILE("hdfs://host:port/user/data/*/test.txt")
4 INTO TABLE `order`
5 COLUMNS TERMINATED BY ","
6 (order_id, order_type, order_status, source_sequence)
7 ORDER BY source_sequence
8)
9WITH BROKER 'bos'
10(
11 ...
12);
通过 ORDER BY 子句配置顺序列。
routine load
1CREATE ROUTINE LOAD example_db.job_name ON order
2COLUMNS(order_id, order_type, order_status, source_sequence),
3ORDER BY source_sequence
4PROPERTIES
5(
6 ...
7)
8FROM KAFKA
9(
10 ...
11);
通过 ORDER BY 子句配置顺序列。
使用示例
下面以 Stream Load 为例,通过一个实际的示例展示顺序列的使用方式和效果。
-
创建支持 Sequence Column 的表
SQL1CREATE TABLE test_table 2( 3 user_id BIGINT, 4 date DATE, 5 group_id BIGINT, 6 keyword VARCHAR(128) 7) 8UNIQUE KEY(user_id, date, group_id) 9DISTRIBUTED BY HASH(user_id, date) BUCKETS 10 10PROPERTIES 11( 12 "function_column.sequence_type" = 'Date' 13)之后我们可以查看到隐藏列:
SQL1mysql> set show_hidden_columns=true; 2Query OK, 0 rows affected (0.00 sec) 3mysql> desc test_table; 4+------------------------+--------------+------+-------+---------+---------+ 5| Field | Type | Null | Key | Default | Extra | 6+------------------------+--------------+------+-------+---------+---------+ 7| user_id | BIGINT | Yes | true | NULL | | 8| date | DATE | Yes | true | NULL | | 9| group_id | BIGINT | Yes | true | NULL | | 10| keyword | VARCHAR(128) | Yes | false | NULL | REPLACE | 11| __DORIS_SEQUENCE_COL__ | DATE | Yes | false | NULL | REPLACE | 12+------------------------+--------------+------+-------+---------+---------+ 135 rows in set (0.00 sec) -
正常导入数据
导入如下数据:
Plain Text11,2020-02-22,1,2020-02-22,a 21,2020-02-22,1,2020-02-22,b 31,2020-02-22,1,2020-03-05,c 41,2020-02-22,1,2020-02-26,d 51,2020-02-22,1,2020-02-22,e 61,2020-02-22,1,2020-02-22,b将 Sequence Column 映射为源数据中的第4列,
modify_date列。Bash1curl --location-trusted -u root: \ 2-H "column_separator: ," \ 3-H "columns: user_id, date, group_id, modify_date, keyword" \ 4-H "function_column.sequence_col: modify_date" \ 5-T testData http://host:port/api/test/test_table/_stream_load结果为
SQL1mysql> select * from test_table; 2+---------+------------+----------+---------+ 3| user_id | date | group_id | keyword | 4+---------+------------+----------+---------+ 5| 1 | 2020-02-22 | 1 | c | 6+---------+------------+----------+---------+我们也可以查看隐藏列的值:
SQL1mysql> set show_hidden_columns=true; 2Query OK, 0 rows affected (0.01 sec) 3 4mysql> select * from test_table; 5+---------+------------+----------+---------+------------------------+ 6| user_id | date | group_id | keyword | __DORIS_SEQUENCE_COL__ | 7+---------+------------+----------+---------+------------------------+ 8| 1 | 2020-02-22 | 1 | c | 2020-03-05 | 9+---------+------------+----------+---------+------------------------+在这次导入中,因 Sequence Column 的值(也就是
modify_date中的值)中2020-03-05为最大值,所以keyword列中最终保留了c。 -
替换顺序的保证
上述步骤完成后,接着导入如下数据:
Plain Text11,2020-02-22,1,2020-02-22,a 21,2020-02-22,1,2020-02-23,b查询数据
SQL1MySQL [test]> select * from test_table; 2+---------+------------+----------+---------+ 3| user_id | date | group_id | keyword | 4+---------+------------+----------+---------+ 5| 1 | 2020-02-22 | 1 | c | 6+---------+------------+----------+---------+由于新导入的数据的 Sequence Column 都小于表中已有的值,则没有替换发生。
再尝试导入如下数据:
Plain Text11,2020-02-22,1,2020-02-22,a 21,2020-02-22,1,2020-03-23,w查询数据:
SQL1MySQL [test]> select * from test_table; 2+---------+------------+----------+---------+ 3| user_id | date | group_id | keyword | 4+---------+------------+----------+---------+ 5| 1 | 2020-02-22 | 1 | w | 6+---------+------------+----------+---------+由于新导入的数据的 Sequence Column 值大于表中的值,所以数据被替换。
