tencent cloud

腾讯云数据仓库 TCHouse-D

产品简介
产品概述
基本概念
集群架构
产品优势
应用场景
购买指南
计费概述
续费说明
到期与欠费说明
退费说明
配置变更计费说明
快速入门
通过控制台使用腾讯云数据仓库 TCHouse-D
通过客户端使用腾讯云数据仓库 TCHouse-D
操作指南
集群操作
监控和告警配置
账户权限管理
数据管理
查询管理
配置管理
节点管理
日志分析
SQL 工作区
开启资源隔离
开发指南
数据表设计
数据导入
数据导出
基础功能
查询优化
生态扩展功能
API 文档
History
Introduction
API Category
Making API Requests
Cluster Operation APIs
Database and Table APIs
Cluster Information Viewing APIs
Hot-Cold Data Layering APIs
Database and Operation Audit APIs
User and Permission APIs
Resource Group Management APIs
Data Types
Error Codes
云上生态
为子账号授予 CAM 策略
查询加速腾讯云 DLC
实践教程
基本功能使用
高级特性使用
资源规格选型及调优建议
命名规范及库表限制
表设计与数据导入
查询调优
建议规避的用法
通过 JDBC 方式公网访问 TCHouse-D
性能测试
TPC-H 性能测试
SSB 性能测试
TPC-DS 性能测试
常见问题
常见操作问题
常见报错
联系我们
词汇表
产品协议
服务等级协议
隐私政策
数据处理和安全协议

数据删除

PDF
聚焦模式
字号
最后更新时间: 2024-06-27 11:07:54

批量删除

目前 Doris 支持 Broker Load(HDFS 数据)Routine Load(Kafka 数据)Stream load(本地文件)等多种导入方式,对于数据的删除目前只能通过 delete 语句进行删除,使用 delete 语句的方式删除时,每执行一次 delete 都会生成一个新的数据版本,如果频繁删除会严重影响查询性能,并且在使用 delete 方式删除时,是通过生成一个空的 rowset 来记录删除条件实现,每次读取都要对删除条件进行过滤,同样在条件较多时会对性能造成影响。 对比其他的系统,greenplum 的实现方式更像是传统数据库产品,snowflake 通过 merge 语法实现。
对于类似于 cdc 数据导入的场景,数据中 insert 和 delete 一般是穿插出现的,面对这种场景我们目前的导入方式也无法满足,即使我们能够分离出 insert 和 delete 虽然可以解决导入的问题,但是仍然解决不了删除的问题。使用批量删除功能可以解决这些个别场景的需求。数据导入有三种合并方式:
1. APPEND:数据全部追加到现有数据中。
2. DELETE:删除所有与导入数据 key 列值相同的行。
3. MERGE:根据 DELETE ON 的决定 APPEND 还是 DELETE。

基本原理

通过增加一个隐藏列__DORIS_DELETE_SIGN__实现,因为我们只是在 unique 模型上做批量删除,因此只需要增加一个类型为 bool 聚合函数为 replace 的隐藏列即可。在 BE 各种聚合写入流程都和正常列一样,读取方案有两个: 在 FE 遇到 select * 等扩展时去掉__DORIS_DELETE_SIGN__列,并且默认加上 __DORIS_DELETE_SIGN__ != true 的条件, BE 读取时都会加上一列进行判断,通过条件确定是否删除。

导入

导入时在 FE 解析时将隐藏列的值设置成 DELETE ON 表达式的值,其他的聚合行为和 replace 的聚合列相同。

读取

读取时在所有存在隐藏列的 olapScanNode 上增加__DORIS_DELETE_SIGN__ != true 的条件,BE 不感知这一过程,正常执行。

Cumulative Compaction

Cumulative Compaction 时将隐藏列看作正常的列处理,Compaction 逻辑没有变化。

Base Compaction

Base Compaction 时要删掉被标记为删除的行,以减少数据占用的空间。

启用批量删除支持

启用批量删除支持有以下两种形式:
1. 通过在 FE 配置文件中增加enable_batch_delete_by_default=true 重启 FE 后新建表的都支持批量删除,此选项默认为 false。
2. 对于没有更改上述 FE 配置或对于以存在的不支持批量删除功能的表,可以使用如下语句: 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__ 列则支持,如果没有则不支持。

语法说明

导入的语法设计方面主要是增加一个指定删除标记列的字段的 colum 映射,并且需要在导入的数据中增加一列,各种导入方式设置的语法如下。

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

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

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"
);

注意事项

1. 由于除Stream Load 外的导入操作在 Doris 内部有可能乱序执行,因此在使用MERGE 方式导入时如果不是Stream Load,需要与 load sequence 一起使用,具体的语法可以参照 Sequence 列 相关的文档。
2. DELETE ON 条件只能与 MERGE 一起使用。

使用示例

查看是否启用批量删除支持

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)

Stream Load 使用示例

1. 正常导入数据:
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
2. 将与导入数据 key 相同的数据全部删除:
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 |
+--------+----------+----------+------+
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 |
+--------+----------+----------+------+

Sql Delete 操作

Delete 不同于其他导入方式,它是一个同步过程,与 Insert into 相似,所有的 Delete 操作在 Doris 中是一个独立的导入作业,一般 Delete 语句需要指定表和分区以及删除的条件来筛选要删除的数据,并将会同时删除 base 表和 rollup 表的数据。Delete 操作的语法详见 DELETE 语法。

返回结果

Delete 命令是一个 SQL 命令,返回结果是同步的,分为以下几种:
1. 执行成功 如果 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'}
2. 提交成功,但未可见。 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,如果不可见则显示COMMITTEDtxnId:这个 Delete job 对应的事务 ID。 err:字段会显示一些本次删除的详细信息。
3. 提交失败,事务取消。 如果 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 操作返回结果的正确处理逻辑为:
1. 如果返回结果为 ERROR 1064 (HY000) ,则表示删除失败。
2. 如果返回结果为 Query OK,则表示删除执行成功。
如果 statusCOMMITTED,表示数据仍不可见,用户可以稍等一段时间再用 show delete 命令查看结果。
如果 statusVISIBLE,表示数据删除成功。

Delete 操作相关 FE 配置

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)

注意事项

不同于 Insert into 命令,delete 不能手动指定label,有关概念可以查看 INSERT INTO 文档。

更多帮助

更多详细语法请参阅 Delete 命令手册,也可以在 Mysql 客户端命令行下输入 HELP DELETE 获取更多帮助信息。

帮助和支持

本页内容是否解决了您的问题?

填写满意度调查问卷,共创更好文档体验。

文档反馈