目前Doris 支持broker load, routine load, stream load 等多种导入方式,对于数据的删除目前只能通过delete 语句进行删除,使用delete 语句的方式删除时,每执行一次delete 都会生成一个新的数据版本,如果频繁删除会严重影响查询性能,并且在使用delete 方式删除时,是通过生成一个空的rowset来记录删除条件实现,每次读取都要对删除跳条件进行过滤,同样在条件较多时会对性能造成影响。对比其他的系统,greenplum 的实现方式更像是传统数据库产品,snowflake 通过merge 语法实现。
对于类似于cdc 数据的导入的场景,数据数据中insert 和delete 一般是穿插出现的,面对这种场景我们目前的导入方式也无法满足,即使我们能够分离出insert 和delete 虽然可以解决导入的问题,但是仍然解决不了删除的问题。使用批量删除功能可以解决这些个场景的需求。
数据导入有三种合并方式:
通过增加一个隐藏列__DELETE_SIGN__实现,因为我们只是在unique 模型上做批量删除,因此只需要增加一个 类型为bool 聚合函数为replace 的隐藏列即可。在be 各种聚合写入流程都和正常列一样,读取方案有两个:
在fe遇到 * 等扩展时去去掉__DELETE_SIGN__,并且默认加上 DELETE_SIGN != true 的条件 be 读取时都会加上一列进行判断,通过条件确定是否删除
读取时在所有存在隐藏列的olapScanNode上增加__DELETE_SIGN__ != true 的条件,be 不感知这以过程,正常执行
Cumulative Compaction 时将隐藏列看作正常的列处理,Compaction逻辑没有变化
Base Compaction 时要将标记为删除的行的删掉,以减少数据占用的空间
导入的语法设计方面主要是增加一个指定删除标记列的字段的column 映射,并且需要在导入数据中增加这一列,各个导入方式设置的方法如下:
stream load:
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=true]
)
WITH BROKER 'broker'
(
"username"="user",
"password"="pass"
)
PROPERTIES
(
"timeout" = "3600"
);
routine load:
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"
);
启用批量删除支持 有两种形式:
如果确定一个表是否支持批量删除,可以通过 设置一个session variable 来显示隐藏列 SET show_hidden_columns=true ,之后使用desc tablename,如果输出中有__DELETE_SIGN__ 列则支持,如果没有则不支持