如何从分区配置单元 table 中删除行?
How to drop rows from partitioned hive table?
我需要从已分区的 Hive table 中删除特定行。这些要删除的行符合某些条件,因此不能删除整个分区。假设 table Table
有三列:partner
、date
和 source_key
,并按 date
和 source_key
.
已知不支持删除或更新配置单元中特定记录集的操作(See How to delete and update a record in Hive)。
在 this solution 之后,我成功执行了以下查询,以便 仅保留 符合某些给定条件的记录,例如:属于 [= 的某个给定范围18=],具有 source_key='heaven'
和列 partner<>'angel'
...
创建 table Table
.
的临时空副本
CREATE TABLE IF NOT EXISTS tmpTable LIKE Table;
用当前行填充它。
INSERT OVERWRITE TABLE tmpTable
PARTITION (date,source_key)
SELECT * FROM Table
WHERE
date >= '2020-05-01' AND date < '2020-11-30' AND
source_key = 'heaven';
删除目标分区。
ALTER TABLE Table DROP IF EXISTS
PARTITION (source_key = 'heaven' , date >= '2020-05-01' , date < '2020-11-30' );
将编辑后的分区插入目标table。 (由于语法错误无法插入 OVERWRITE)
INSERT INTO Table
PARTITION (source_key,date)
SELECT * FROM tmpTable
WHERE
partner <> 'angel';
临时删除 table。
DROP TABLE IF EXISTS tmpTable;
查询运行正常。因为 table Table
是托管的,当分区被删除时,hdfs 文件应该被删除,但是有些地方是错误的(可能在最后一个 INSERT INTO 语句中)因为在执行所有这些查询之后target table Table
保留给定日期范围内 partner = 'angel'
的所有记录,基本上保持不变。
错在哪里?什么东西少了?如何为这样的 Hive 准确删除符合特定条件的特定行 table?
Table 分区可以直接从 select 自身 + WHERE 过滤器覆盖。场景很简单,不需要任何临时的table。如果您不确定会发生什么,请进行备份 table。
如果要删除整个分区(不覆盖),执行
ALTER TABLE TableName DROP IF EXISTS
PARTITION (<partition spec to be dropped>); --check partition spec to be dropped carefully
如果没有要删除的分区,请跳过此步骤。
用筛选的行覆盖其他分区:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
set hive.allow.move.on.s3=true; --If you are on Qubole/S3
insert overwrite table TableName partition (date, source_key ) --partition spec should match table DDL
select * from TableName
where <condition> --condition should be True for rows which NOT be deleted
您的代码相当混乱,因为您使用 LIKE 创建临时 table 但使用不同的分区规范和 selecting *(与原始 table 中的列顺序相同)。列的顺序必须完全匹配,分区列是最后的,也是相同的顺序。
我需要从已分区的 Hive table 中删除特定行。这些要删除的行符合某些条件,因此不能删除整个分区。假设 table Table
有三列:partner
、date
和 source_key
,并按 date
和 source_key
.
已知不支持删除或更新配置单元中特定记录集的操作(See How to delete and update a record in Hive)。
在 this solution 之后,我成功执行了以下查询,以便 仅保留 符合某些给定条件的记录,例如:属于 [= 的某个给定范围18=],具有 source_key='heaven'
和列 partner<>'angel'
...
创建 table Table
.
CREATE TABLE IF NOT EXISTS tmpTable LIKE Table;
用当前行填充它。
INSERT OVERWRITE TABLE tmpTable
PARTITION (date,source_key)
SELECT * FROM Table
WHERE
date >= '2020-05-01' AND date < '2020-11-30' AND
source_key = 'heaven';
删除目标分区。
ALTER TABLE Table DROP IF EXISTS
PARTITION (source_key = 'heaven' , date >= '2020-05-01' , date < '2020-11-30' );
将编辑后的分区插入目标table。 (由于语法错误无法插入 OVERWRITE)
INSERT INTO Table
PARTITION (source_key,date)
SELECT * FROM tmpTable
WHERE
partner <> 'angel';
临时删除 table。
DROP TABLE IF EXISTS tmpTable;
查询运行正常。因为 table Table
是托管的,当分区被删除时,hdfs 文件应该被删除,但是有些地方是错误的(可能在最后一个 INSERT INTO 语句中)因为在执行所有这些查询之后target table Table
保留给定日期范围内 partner = 'angel'
的所有记录,基本上保持不变。
错在哪里?什么东西少了?如何为这样的 Hive 准确删除符合特定条件的特定行 table?
Table 分区可以直接从 select 自身 + WHERE 过滤器覆盖。场景很简单,不需要任何临时的table。如果您不确定会发生什么,请进行备份 table。
如果要删除整个分区(不覆盖),执行
ALTER TABLE TableName DROP IF EXISTS PARTITION (<partition spec to be dropped>); --check partition spec to be dropped carefully
如果没有要删除的分区,请跳过此步骤。
用筛选的行覆盖其他分区:
set hive.exec.dynamic.partition=true; set hive.exec.dynamic.partition.mode=nonstrict; set hive.allow.move.on.s3=true; --If you are on Qubole/S3 insert overwrite table TableName partition (date, source_key ) --partition spec should match table DDL select * from TableName where <condition> --condition should be True for rows which NOT be deleted
您的代码相当混乱,因为您使用 LIKE 创建临时 table 但使用不同的分区规范和 selecting *(与原始 table 中的列顺序相同)。列的顺序必须完全匹配,分区列是最后的,也是相同的顺序。