目前Doris 支持 Broker Load,Routine Load, Stream Load 等多种导入方式,对于数据的删除目前只能通过delete语句进行删除,使用delete 语句的方式删除时,每执行一次delete 都会生成一个新的数据版本,如果频繁删除会严重影响查询性能,并且在使用delete方式删除时,是通过生成一个空的rowset来记录删除条件实现,每次读取都要对删除条件进行过滤,同样在条件较多时会对性能造成影响。对比其他的系统,greenplum 的实现方式更像是传统数据库产品,snowflake 通过merge 语法实现。
对于类似于cdc数据导入的场景,数据中insert和delete一般是穿插出现的,面对这种场景我们目前的导入方式也无法满足,即使我们能够分离出insert和delete虽然可以解决导入的问题,但是仍然解决不了删除的问题。使用批量删除功能可以解决这些个别场景的需求。数据导入有三种合并方式:
通过增加一个隐藏列__DORIS_DELETE_SIGN__
实现,因为我们只是在unique 模型上做批量删除,因此只需要增加一个类型为bool 聚合函数为replace 的隐藏列即可。在be 各种聚合写入流程都和正常列一样,读取方案有两个:
在fe遇到 * 等扩展时去掉__DORIS_DELETE_SIGN__
,并且默认加上 __DORIS_DELETE_SIGN__ != true
的条件, be 读取时都会加上一列进行判断,通过条件确定是否删除。
导入时在fe 解析时将隐藏列的值设置成 DELETE ON
表达式的值,其他的聚合行为和replace的聚合列相同。
读取时在所有存在隐藏列的olapScanNode上增加__DORIS_DELETE_SIGN__ != true
的条件,be 不感知这一过程,正常执行。
Cumulative Compaction 时将隐藏列看作正常的列处理,Compaction逻辑没有变化。
Base Compaction 时要将标记为删除的行的删掉,以减少数据占用的空间。
启用批量删除支持有一下两种形式:
enable_batch_delete_by_default=true
重启fe 后新建表的都支持批量删除,此选项默认为false;ALTER TABLE tablename ENABLE FEATURE "BATCH_DELETE"
来启用批量删除。本操作本质上是一个schema change 操作,操作立即返回,可以通过show alter table column
来确认操作是否完成。那么如何确定一个表是否支持批量删除,可以通过设置一个session variable 来显示隐藏列 SET show_hidden_columns=true
,之后使用desc tablename
,如果输出中有__DORIS_DELETE_SIGN__
列则支持,如果没有则不支持。
导入的语法设计方面主要是增加一个指定删除标记列的字段的column映射,并且需要在导入的数据中增加一列,各种导入方式设置的语法如下
Stream Load
的写法在header 中的 columns 字段增加一个设置删除标记列的字段, 示例 -H "columns: k1, k2, label_c3" -H "merge_type: [MERGE|APPEND|DELETE]" -H "delete: label_c3=1"
。
Broker Load
的写法在 PROPERTIES
处设置删除标记列的字段,语法如下:
LOAD LABEL db1.label1
(
[MERGE|APPEND|DELETE] DATA INFILE("hdfs://abc.com:8888/user/palo/test/ml/file1")
INTO TABLE tbl1
COLUMNS TERMINATED BY ","
(tmp_c1,tmp_c2, label_c3)
SET
(
id=tmp_c2,
name=tmp_c1,
)
[DELETE ON label_c3=true]
)
WITH BROKER 'broker'
(
"username"="user",
"password"="pass"
)
PROPERTIES
(
"timeout" = "3600"
);
Routine Load
的写法在 columns
字段增加映射,映射方式同上,语法如下:
CREATE ROUTINE LOAD example_db.test1 ON example_tbl
[WITH MERGE|APPEND|DELETE]
COLUMNS(k1, k2, k3, v1, v2, label),
WHERE k1 > 100 and k2 like "%doris%"
[DELETE ON label=true]
PROPERTIES
(
"desired_concurrent_number"="3",
"max_batch_interval" = "20",
"max_batch_rows" = "300000",
"max_batch_size" = "209715200",
"strict_mode" = "false"
)
FROM KAFKA
(
"kafka_broker_list" = "broker1:9092,broker2:9092,broker3:9092",
"kafka_topic" = "my_topic",
"kafka_partitions" = "0,1,2,3",
"kafka_offsets" = "101,0,0,200"
);
Stream Load
外的导入操作在doris 内部有可能乱序执行,因此在使用MERGE
方式导入时如果不是Stream Load
,需要与 load sequence 一起使用,具体的 语法可以参照sequence列 相关的文档;DELETE ON
条件只能与 MERGE 一起使用。SET show_hidden_columns = true
的session variable来查看表是否支持批量删除, 按示例完成DELETE/MERGE的导入作业后, 如果在同一个session中执行select count(*) from xxx
等语句时, 需要执行SET show_hidden_columns = false
或者开启新的session, 避免查询结果中包含那些被批量删除的记录, 导致结果与预期不符.mysql> SET show_hidden_columns=true;
Query OK, 0 rows affected (0.00 sec)
mysql> DESC test;
+-----------------------+--------------+------+-------+---------+---------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------+--------------+------+-------+---------+---------+
| name | VARCHAR(100) | No | true | NULL | |
| gender | VARCHAR(10) | Yes | false | NULL | REPLACE |
| age | INT | Yes | false | NULL | REPLACE |
| __DORIS_DELETE_SIGN__ | TINYINT | No | false | 0 | REPLACE |
+-----------------------+--------------+------+-------+---------+---------+
4 rows in set (0.00 sec)
curl --location-trusted -u root: -H "column_separator:," -H "columns: siteid, citycode, username, pv" -H "merge_type: APPEND" -T ~/table1_data http://127.0.0.1:8130/api/test/table1/_stream_load
其中的APPEND 条件可以省略,与下面的语句效果相同:
curl --location-trusted -u root: -H "column_separator:," -H "columns: siteid, citycode, username, pv" -T ~/table1_data http://127.0.0.1:8130/api/test/table1/_stream_load
curl --location-trusted -u root: -H "column_separator:," -H "columns: siteid, citycode, username, pv" -H "merge_type: DELETE" -T ~/table1_data http://127.0.0.1:8130/api/test/table1/_stream_load
假设导入表中原有数据为:
+--------+----------+----------+------+
| siteid | citycode | username | pv |
+--------+----------+----------+------+
| 3 | 2 | tom | 2 |
| 4 | 3 | bush | 3 |
| 5 | 3 | helen | 3 |
+--------+----------+----------+------+
导入数据为:
3,2,tom,0
导入后数据变成:
+--------+----------+----------+------+
| siteid | citycode | username | pv |
+--------+----------+----------+------+
| 4 | 3 | bush | 3 |
| 5 | 3 | helen | 3 |
+--------+----------+----------+------+
site_id=1
的行的key列相同的行curl --location-trusted -u root: -H "column_separator:," -H "columns: siteid, citycode, username, pv" -H "merge_type: MERGE" -H "delete: siteid=1" -T ~/table1_data http://127.0.0.1:8130/api/test/table1/_stream_load
假设导入前数据为:
+--------+----------+----------+------+
| siteid | citycode | username | pv |
+--------+----------+----------+------+
| 4 | 3 | bush | 3 |
| 5 | 3 | helen | 3 |
| 1 | 1 | jim | 2 |
+--------+----------+----------+------+
导入数据为:
2,1,grace,2
3,2,tom,2
1,1,jim,2
导入后为:
+--------+----------+----------+------+
| siteid | citycode | username | pv |
+--------+----------+----------+------+
| 4 | 3 | bush | 3 |
| 2 | 1 | grace | 2 |
| 3 | 2 | tom | 2 |
| 5 | 3 | helen | 3 |
+--------+----------+----------+------+
curl --location-trusted -u root: -H "column_separator:," -H "columns: name, gender, age" -H "function_column.sequence_col: age" -H "merge_type: DELETE" -T ~/table1_data http://127.0.0.1:8130/api/test/table1/_stream_load
当unique表设置了sequence列时,在相同key列下,sequence列的值会作为REPLACE聚合函数替换顺序的依据,较大值可以替换较小值。 当对这种表基于__DORIS_DELETE_SIGN__
进行删除标记时,需要保证key相同和sequence列值要大于等于当前值。
假设有表,结构如下
mysql> SET show_hidden_columns=true;
Query OK, 0 rows affected (0.00 sec)
mysql> DESC table1;
+------------------------+--------------+------+-------+---------+---------+
| Field | Type | Null | Key | Default | Extra |
+------------------------+--------------+------+-------+---------+---------+
| name | VARCHAR(100) | No | true | NULL | |
| gender | VARCHAR(10) | Yes | false | NULL | REPLACE |
| age | INT | Yes | false | NULL | REPLACE |
| __DORIS_DELETE_SIGN__ | TINYINT | No | false | 0 | REPLACE |
| __DORIS_SEQUENCE_COL__ | INT | Yes | false | NULL | REPLACE |
+------------------------+--------------+------+-------+---------+---------+
4 rows in set (0.00 sec)
假设导入表中原有数据为:
+-------+--------+------+
| name | gender | age |
+-------+--------+------+
| li | male | 10 |
| wang | male | 14 |
| zhang | male | 12 |
+-------+--------+------+
当导入数据为:
li,male,10
导入后数据后会变成:
+-------+--------+------+
| name | gender | age |
+-------+--------+------+
| wang | male | 14 |
| zhang | male | 12 |
+-------+--------+------+
会发现数据
li,male,10
被删除成功。
但是假如导入数据为:
li,male,9
导入后数据会变成:
+-------+--------+------+
| name | gender | age |
+-------+--------+------+
| li | male | 10 |
| wang | male | 14 |
| zhang | male | 12 |
+-------+--------+------+
会看到数据
li,male,10
并没有被删除,这是因为在底层的依赖关系上,会先判断key相同的情况,对外展示sequence列的值大的行数据,然后在看该行的__DORIS_DELETE_SIGN__
值是否为1,如果为1则不会对外展示,如果为0,则仍会读出来。
当导入数据中同时存在数据写入和删除时(例如Flink CDC场景中),使用seq列可以有效的保证当数据乱序到达时的一致性,避免后到达的一个旧版本的删除操作,误删掉了先到达的新版本的数据。
本文主要讲述如果我们需要修改或更新Doris中的数据,如何使用UPDATE命令来操作。数据更新对Doris的版本有限制,只能在Doris Version 0.15.x + 才可以使用。
利用查询引擎自身的 where 过滤逻辑,从待更新表中筛选出需要被更新的行。再利用 Unique 模型自带的 Value 列新数据替换旧数据的逻辑,将待更新的行变更后,再重新插入到表中,从而实现行级别更新。
Update 语法在Doris中是一个同步语法,即 Update 语句执行成功,更新操作也就完成了,数据是可见的。
Update 语句的性能和待更新的行数以及 condition 的检索效率密切相关。
默认情况下,并不允许同一时间对同一张表并发进行多个 Update 操作。
主要原因是,Doris 目前支持的是行更新,这意味着,即使用户声明的是 SET v2 = 1
,实际上,其他所有的 Value 列也会被覆盖一遍(尽管值没有变化)。
这就会存在一个问题,如果同时有两个 Update 操作对同一行进行更新,那么其行为可能是不确定的,也就是可能存在脏数据。
但在实际应用中,如果用户自己可以保证即使并发更新,也不会同时对同一行进行操作的话,就可以手动打开并发限制。通过修改 FE 配置 enable_concurrent_update
,当配置值为 true 时,则对更新并发无限制。
注:开启配置后,会有一定的性能风险,可参考上面的性能小节部分,提升更新效率。
由于 Doris 目前支持的是行更新,并且采用的是读取后再写入的两步操作,则如果 Update 语句和其他导入或 Delete 语句刚好修改的是同一行时,存在不确定的数据结果。
所以用户在使用的时候,一定要注意用户侧自己进行 Update 语句和其他 DML 语句的并发控制。
假设 Doris 中存在一张订单表,其中 订单id 是 Key 列,订单状态,订单金额是 Value 列。数据状态如下:
订单id | 订单金额 | 订单状态 |
---|---|---|
1 | 100 | 待付款 |
+----------+--------------+--------------+
| order_id | order_amount | order_status |
+----------+--------------+--------------+
| 1 | 100 | 待付款 |
+----------+--------------+--------------+
1 row in set (0.01 sec)
这时候,用户点击付款后,Doris 系统需要将订单id 为 '1' 的订单状态变更为 '待发货',就需要用到 Update 功能。
mysql> UPDATE test_order SET order_status = '待发货' WHERE order_id = 1;
Query OK, 1 row affected (0.11 sec)
{'label':'update_20ae22daf0354fe0-b5aceeaaddc666c5', 'status':'VISIBLE', 'txnId':'33', 'queryId':'20ae22daf0354fe0-b5aceeaaddc666c5'}
更新后结果如下
+----------+--------------+--------------+
| order_id | order_amount | order_status |
+----------+--------------+--------------+
| 1 | 100 | 待发货 |
+----------+--------------+--------------+
1 row in set (0.01 sec)
用户执行 UPDATE 命令后,系统会进行如下三步:
第一步:读取满足 WHERE 订单id=1 的行 (1,100,'待付款')
第二步:变更该行的订单状态,从'待付款'改为'待发货' (1,100,'待发货')
第三步:将更新后的行再插入回表中,从而达到更新的效果。
订单id | 订单金额 | 订单状态 |
---|---|---|
1 | 100 | 待付款 |
1 | 100 | 待发货 |
由于表 test_order 是 UNIQUE 模型,所以相同 Key 的行,之后后者才会生效,所以最终效果如下:
订单id | 订单金额 | 订单状态 |
---|---|---|
1 | 100 | 待发货 |
目前Update操作只支持更新Value列,Key列的更新可参考使用FlinkCDC更新Key列
关于 数据更新 使用的更多详细语法,请参阅 update 命令手册,也可以在Mysql客户端命令行下输入 HELP UPDATE
获取更多帮助信息。
Delete不同于其他导入方式,它是一个同步过程,与Insert into相似,所有的Delete操作在Doris中是一个独立的导入作业,一般Delete语句需要指定表和分区以及删除的条件来筛选要删除的数据,并将会同时删除base表和rollup表的数据。
delete操作的语法详见官网 DELETE 语法。
Delete命令是一个SQL命令,返回结果是同步的,分为以下几种:
执行成功
如果Delete顺利执行完成并可见,将返回下列结果,Query OK
表示成功
mysql> delete from test_tbl PARTITION p1 where k1 = 1;
Query OK, 0 rows affected (0.04 sec)
{'label':'delete_e7830c72-eb14-4cb9-bbb6-eebd4511d251', 'status':'VISIBLE', 'txnId':'4005'}
提交成功,但未可见
Doris的事务提交分为两步:提交和发布版本,只有完成了发布版本步骤,结果才对用户是可见的。若已经提交成功了,那么就可以认为最终一定会发布成功,Doris会尝试在提交完后等待发布一段时间,如果超时后即使发布版本还未完成也会优先返回给用户,提示用户提交已经完成。若如果Delete已经提交并执行,但是仍未发布版本和可见,将返回下列结果
mysql> delete from test_tbl PARTITION p1 where k1 = 1;
Query OK, 0 rows affected (0.04 sec)
{'label':'delete_e7830c72-eb14-4cb9-bbb6-eebd4511d251', 'status':'COMMITTED', 'txnId':'4005', 'err':'delete job is committed but may be taking effect later' }
结果会同时返回一个json字符串:
affected rows
:表示此次删除影响的行,由于Doris的删除目前是逻辑删除,因此对于这个值是恒为0;
label
:自动生成的 label,是该导入作业的标识。每个导入作业,都有一个在单 database 内部唯一的 Label;
status
:表示数据删除是否可见,如果可见则显示VISIBLE
,如果不可见则显示COMMITTED
;
txnId
:这个Delete job对应的事务id;
err
:字段会显示一些本次删除的详细信息。
提交失败,事务取消
如果Delete语句没有提交成功,将会被Doris自动中止,返回下列结果
mysql> delete from test_tbl partition p1 where k1 > 80;
ERROR 1064 (HY000): errCode = 2, detailMessage = {错误原因}
示例:
比如说一个超时的删除,将会返回timeout时间和未完成的(tablet=replica)
mysql> delete from test_tbl partition p1 where k1 > 80;
ERROR 1064 (HY000): errCode = 2, detailMessage = failed to delete replicas from job: 4005, Unfinished replicas:10000=60000, 10001=60000, 10002=60000
综上,对于Delete操作返回结果的正确处理逻辑为:
ERROR 1064 (HY000)
,则表示删除失败;Query OK
,则表示删除执行成功;
status
为COMMITTED
,表示数据仍不可见,用户可以稍等一段时间再用show delete
命令查看结果;status
为VISIBLE
,表示数据删除成功。TIMEOUT配置
总体来说,Doris的删除作业的超时时间限制在30秒到5分钟时间内,具体时间可通过下面配置项调整
tablet_delete_timeout_second
delete自身的超时时间是可受指定分区下tablet的数量弹性改变的,此项配置为平均一个tablet所贡献的timeout时间,默认值为2。
假设此次删除所指定分区下有5个tablet,那么可提供给delete的timeout时间为10秒,由于低于最低超时时间30秒,因此最终超时时间为30秒。
load_straggler_wait_second
如果用户预估的数据量确实比较大,使得5分钟的上限不足时,用户可以通过此项调整timeout上限,默认值为300。
TIMEOUT的具体计算规则为(秒)
TIMEOUT = MIN(load_straggler_wait_second, MAX(30, tablet_delete_timeout_second * tablet_num))
query_timeout
因为delete本身是一个SQL命令,因此删除语句也会受session限制,timeout还受Session中的query_timeout
值影响,可以通过SET query_timeout = xxx
来增加超时时间,单位是秒。
IN谓词配置
max_allowed_in_element_num_of_delete
如果用户在使用in谓词时需要占用的元素比较多,用户可以通过此项调整允许携带的元素上限,默认值为1024。
用户可以通过show delete语句查看历史上已执行完成的删除记录。
语法如下
SHOW DELETE [FROM db_name]
使用示例
mysql> show delete from test_db;
+-----------+---------------+---------------------+-----------------+----------+
| TableName | PartitionName | CreateTime | DeleteCondition | State |
+-----------+---------------+---------------------+-----------------+----------+
| empty_tbl | p3 | 2020-04-15 23:09:35 | k1 EQ "1" | FINISHED |
| test_tbl | p4 | 2020-04-15 23:09:53 | k1 GT "80" | FINISHED |
+-----------+---------------+---------------------+-----------------+----------+
2 rows in set (0.00 sec)
label
,有关 label 的概念可以查看Insert Into 文档。关于 delete 使用的更多详细语法,请参阅 delete 命令手册,也可以在Mysql客户端命令行下输入 HELP DELETE
获取更多帮助信息。
Uniq模型主要针对需要唯一主键的场景,可以保证主键唯一性约束,但是由于使用REPLACE聚合方式,在同一批次中导入的数据,替换顺序不做保证,详细介绍可以参考数据模型。替换顺序无法保证则无法确定最终导入到表中的具体数据,存在了不确定性。
为了解决这个问题,Doris支持了sequence列,通过用户在导入时指定sequence列,相同key列下,REPLACE聚合类型的列将按照sequence列的值进行替换,较大值可以替换较小值,反之则无法替换。该方法将顺序的确定交给了用户,由用户控制替换顺序。
sequence列目前只支持Uniq模型。
Sequence列只能在Uniq数据模型下使用。
通过增加一个隐藏列__DORIS_SEQUENCE_COL__
实现,该列的类型由用户在建表时指定,在导入时确定该列具体值,并依据该值对REPLACE列进行替换。
创建Uniq表时,将按照用户指定类型自动添加一个隐藏列__DORIS_SEQUENCE_COL__
。
导入时,fe在解析的过程中将隐藏列的值设置成 order by
表达式的值(broker load和routine load),或者function_column.sequence_col
表达式的值(stream load),value列将按照该值进行替换。隐藏列__DORIS_SEQUENCE_COL__
的值既可以设置为数据源中一列,也可以是表结构中的一列。
请求包含value列时需要额外读取__DORIS_SEQUENCE_COL__
列,该列用于在相同key列下,REPLACE聚合函数替换顺序的依据,较大值可以替换较小值,反之则不能替换。
Cumulative Compaction 时和读取过程原理相同。
Base Compaction 时读取过程原理相同。
Sequence列建表时有两种方式,一种是建表时设置sequence_col
属性,一种是建表时设置sequence_type
属性。
sequence_col
(推荐)创建Uniq表时,指定sequence列到表中其他column的映射
PROPERTIES (
"function_column.sequence_col" = 'column_name',
);
sequence_col用来指定sequence列到表中某一列的映射,该列可以为整型和时间类型(DATE、DATETIME),创建后不能更改该列的类型。
导入方式和没有sequence列时一样,使用相对比较简单,推荐使用。
sequence_type
创建Uniq表时,指定sequence列类型
PROPERTIES (
"function_column.sequence_type" = 'Date',
);
sequence_type用来指定sequence列的类型,可以为整型和时间类型(DATE、DATETIME)。
导入时需要指定sequence列到其他列的映射。
Stream Load
stream load 的写法是在header中的function_column.sequence_col
字段添加隐藏列对应的source_sequence的映射, 示例
curl --location-trusted -u root -H "columns: k1,k2,source_sequence,v1,v2" -H "function_column.sequence_col: source_sequence" -T testData http://host:port/api/testDb/testTbl/_stream_load
Broker Load
在ORDER BY
处设置隐藏列映射的source_sequence字段
LOAD LABEL db1.label1
(
DATA INFILE("hdfs://host:port/user/data/*/test.txt")
INTO TABLE `tbl1`
COLUMNS TERMINATED BY ","
(k1,k2,source_sequence,v1,v2)
ORDER BY source_sequence
)
WITH BROKER 'broker'
(
"username"="user",
"password"="pass"
)
PROPERTIES
(
"timeout" = "3600"
);
Routine Load
映射方式同上,示例如下
CREATE ROUTINE LOAD example_db.test1 ON example_tbl
[WITH MERGE|APPEND|DELETE]
COLUMNS(k1, k2, source_sequence, v1, v2),
WHERE k1 > 100 and k2 like "%doris%"
[ORDER BY source_sequence]
PROPERTIES
(
"desired_concurrent_number"="3",
"max_batch_interval" = "20",
"max_batch_rows" = "300000",
"max_batch_size" = "209715200",
"strict_mode" = "false"
)
FROM KAFKA
(
"kafka_broker_list" = "broker1:9092,broker2:9092,broker3:9092",
"kafka_topic" = "my_topic",
"kafka_partitions" = "0,1,2,3",
"kafka_offsets" = "101,0,0,200"
);
在新建表时如果设置了function_column.sequence_col
或者function_column.sequence_type
,则新建表将支持sequence column。 对于一个不支持sequence column的表,如果想要使用该功能,可以使用如下语句: ALTER TABLE example_db.my_table ENABLE FEATURE "SEQUENCE_LOAD" WITH PROPERTIES ("function_column.sequence_type" = "Date")
来启用。 如果不确定一个表是否支持sequence column,可以通过设置一个session variable来显示隐藏列 SET show_hidden_columns=true
,之后使用desc tablename
,如果输出中有__DORIS_SEQUENCE_COL__
列则支持,如果没有则不支持。
下面以Stream Load为例为示例来展示使用方式:
创建unique模型的test_table数据表,并指定sequence列映射到表中的modify_date列。
CREATE TABLE test.test_table
(
user_id bigint,
date date,
group_id bigint,
modify_date date,
keyword VARCHAR(128)
)
UNIQUE KEY(user_id, date, group_id)
DISTRIBUTED BY HASH (user_id) BUCKETS 32
PROPERTIES(
"function_column.sequence_col" = 'modify_date',
"replication_num" = "1",
"in_memory" = "false"
);
表结构如下:
MySQL > desc test_table;
+-------------+--------------+------+-------+---------+---------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-------+---------+---------+
| user_id | BIGINT | No | true | NULL | |
| date | DATE | No | true | NULL | |
| group_id | BIGINT | No | true | NULL | |
| modify_date | DATE | No | false | NULL | REPLACE |
| keyword | VARCHAR(128) | No | false | NULL | REPLACE |
+-------------+--------------+------+-------+---------+---------+
导入如下数据
1 2020-02-22 1 2020-02-21 a
1 2020-02-22 1 2020-02-22 b
1 2020-02-22 1 2020-03-05 c
1 2020-02-22 1 2020-02-26 d
1 2020-02-22 1 2020-02-23 e
1 2020-02-22 1 2020-02-24 b
此处以stream load为例
curl --location-trusted -u root: -T testData http://host:port/api/test/test_table/_stream_load
结果为
MySQL > select * from test_table;
+---------+------------+----------+-------------+---------+
| user_id | date | group_id | modify_date | keyword |
+---------+------------+----------+-------------+---------+
| 1 | 2020-02-22 | 1 | 2020-03-05 | c |
+---------+------------+----------+-------------+---------+
在这次导入中,因sequence column的值(也就是modify_date中的值)中'2020-03-05'为最大值,所以keyword列中最终保留了c。
上述步骤完成后,接着导入如下数据
1 2020-02-22 1 2020-02-22 a
1 2020-02-22 1 2020-02-23 b
查询数据
MySQL [test]> select * from test_table;
+---------+------------+----------+-------------+---------+
| user_id | date | group_id | modify_date | keyword |
+---------+------------+----------+-------------+---------+
| 1 | 2020-02-22 | 1 | 2020-03-05 | c |
+---------+------------+----------+-------------+---------+
在这次导入的数据中,会比较所有已导入数据的sequence column(也就是modify_date),其中'2020-03-05'为最大值,所以keyword列中最终保留了c。
再尝试导入如下数据
1 2020-02-22 1 2020-02-22 a
1 2020-02-22 1 2020-03-23 w
查询数据
MySQL [test]> select * from test_table;
+---------+------------+----------+-------------+---------+
| user_id | date | group_id | modify_date | keyword |
+---------+------------+----------+-------------+---------+
| 1 | 2020-02-22 | 1 | 2020-03-23 | w |
+---------+------------+----------+-------------+---------+
此时就可以替换表中原有的数据。综上,在导入过程中,会比较所有批次的sequence列值,选择值最大的记录导入Doris表中。
Table test_tbl has sequence column, need to specify the sequence column