Hive insert overwrite 问题

微信公众号:苏言论
理论联系实际,畅言技术与生活。

1 测试的版本

Apache hive 1.1.0/2.3.1/3.1.0

2 insert overwrite使用说明

表类型使用场景hive操作逻辑
非分区表insert overwrite table t select col from b先删除现有数据表目录,再插入新的数据,不存在旧数据保留的情况
分区表insert overwrite table t partition(part_name=’’) select col from b先删除现有分区数据目录,再插入新的数据,不存在旧数据保留的情况
分区表insert overwrite table t select col,part_name from b只对新数据集中存在数据变更的分区进行覆盖,不涉及数据变更的分区和旧数据会被保留

3 示例

考虑下面的课程安排表数据结构和数据;

drop table class_course_schedule;
create table class_course_schedule(id int,course_name string,course_time date) partitioned by(city string);
insert into class_course_schedule values
(1,'语文','2020-02-01','guangzhou'),
(2,'语文','2020-02-02','guangzhou'),
(10,'语文','2020-02-03','guangzhou'),
(3,'政治','2020-02-01','hangzhou'),
(4,'体育','2020-02-02','hangzhou'),
(5,'英语','2020-02-03','hangzhou'),
(6,'音乐','2020-02-01','shanghai'),
(7,'物理','2020-02-02','shanghai'),
(8,'计算机','2020-02-03','shanghai'),
(9,'画图','2020-02-04','shanghai');

select * from class_course_schedule t;
+-------+----------------+----------------+------------+
| t.id  | t.course_name  | t.course_time  |   t.city   |
+-------+----------------+----------------+------------+
| 1     | 语文           | 2020-02-01     | guangzhou  |
| 2     | 语文           | 2020-02-02     | guangzhou  |
| 10    | 语文           | 2020-02-03     | guangzhou  |
| 3     | 政治           | 2020-02-01     | hangzhou   |
| 4     | 体育           | 2020-02-02     | hangzhou   |
| 5     | 英语           | 2020-02-03     | hangzhou   |
| 6     | 音乐           | 2020-02-01     | shanghai   |
| 7     | 物理           | 2020-02-02     | shanghai   |
| 8     | 计算机         | 2020-02-03     | shanghai   |
| 9     | 画图           | 2020-02-04     | shanghai   |
+-------+----------------+----------------+------------+
10 rows selected (1.459 seconds)

对表进行insert overwrite,比如;

insert overwrite table class_course_schedule select * from class_course_schedule where course_name!='语文';

由于city='guangzhou’只有course_name='语文’的数据记录,select返回的数据集中city='guangzhou’分区的数据没有变化,hive从返回的select数据集中删除整个city='guangzhou’分区的情况下进行过滤,所以旧分区(city=‘guangzhou’)没有被重写,数据被保留;

select * from class_course_schedule t;
+-------+----------------+----------------+------------+
| t.id  | t.course_name  | t.course_time  |   t.city   |
+-------+----------------+----------------+------------+
| 1     | 语文           | 2020-02-01     | guangzhou  |
| 2     | 语文           | 2020-02-02     | guangzhou  |
| 10    | 语文           | 2020-02-03     | guangzhou  |
| 3     | 政治           | 2020-02-01     | hangzhou   |
| 4     | 体育           | 2020-02-02     | hangzhou   |
| 5     | 英语           | 2020-02-03     | hangzhou   |
| 6     | 音乐           | 2020-02-01     | shanghai   |
| 7     | 物理           | 2020-02-02     | shanghai   |
| 8     | 计算机         | 2020-02-03     | shanghai   |
| 9     | 画图           | 2020-02-04     | shanghai   |
+-------+----------------+----------------+------------+
10 rows selected (1.459 seconds)

hive按设计工作,因为只需要覆盖所需分区的情况,对于增量分区负载来说是正常的,在这种情况下,无需触摸其它分区;如果覆盖无需更改的分区,则会导致非必要数据丢失,恢复起来可能会非常昂贵
再对表进行insert overwrite;

insert overwrite table class_course_schedule select * from class_course_schedule where course_name!='英语';

由于 course_name='英语’所在的分区city='hangzhou’中course_name非一致数据,select返回的数据集中city='guangzhou’分区的数据有变化,hive对其重写;

+-------+----------------+----------------+------------+
| t.id  | t.course_name  | t.course_time  |   t.city   |
+-------+----------------+----------------+------------+
| 1     | 语文           | 2020-02-01     | guangzhou  |
| 2     | 语文           | 2020-02-02     | guangzhou  |
| 10    | 语文           | 2020-02-03     | guangzhou  |
| 3     | 政治           | 2020-02-01     | hangzhou   |
| 4     | 体育           | 2020-02-02     | hangzhou   |
| 6     | 音乐           | 2020-02-01     | shanghai   |
| 7     | 物理           | 2020-02-02     | shanghai   |
| 8     | 计算机         | 2020-02-03     | shanghai   |
| 9     | 画图           | 2020-02-04     | shanghai   |
+-------+----------------+----------------+------------+
9 rows selected (0.562 seconds)

4 建议的操作

  1. 分区表指定具体分区,减少对不相关分区的影响;
insert overwrite table class_course_schedule partition(city='guangzhou') values
(12,'语文01','2020-02-12'),
(22,'语文02','2020-02-22'),
(19,'语文03','2020-02-19');

+-------+----------------+----------------+------------+
| t.id  | t.course_name  | t.course_time  |   t.city   |
+-------+----------------+----------------+------------+
| 12    | 语文01         | 2020-02-12     | guangzhou  |
| 22    | 语文02         | 2020-02-22     | guangzhou  |
| 19    | 语文03         | 2020-02-19     | guangzhou  |
| 3     | 政治           | 2020-02-01     | hangzhou   |
| 4     | 体育           | 2020-02-02     | hangzhou   |
| 6     | 音乐           | 2020-02-01     | shanghai   |
| 7     | 物理           | 2020-02-02     | shanghai   |
| 8     | 计算机         | 2020-02-03     | shanghai   |
| 9     | 画图           | 2020-02-04     | shanghai   |
+-------+----------------+----------------+------------+
9 rows selected (0.574 seconds)
  1. 如果仍然要删除分区,可以删除/重建表(可能需要为此再创建一个中间表),然后将分区加载到其中;或者计算需要单独删除的分区,然后执行ALTER TABLE DROP PARTITION删除分区。

5 参考链接

Inserting datain to HiveTables from queries

### 使用 Hive 进行数据覆盖插入操作 在 Hive 中,`INSERT OVERWRITE TABLE` 命令用于向现有表中插入新记录并替换旧有数据。此命令会删除目标表中的任何已有数据,并写入新的查询结果。 #### 语法结构 基本语法如下: ```sql INSERT OVERWRITE TABLE target_table_name SELECT column_list FROM source_table_name; ``` 为了确保最佳性能,在执行 `INSERT OVERWRITE` 操作时应考虑以下几点建议[^1]: - 将最大的表格放在连接语句最右侧的位置; - 只选择必要的字段以减少 I/O 开销; 下面是一个具体的例子来展示如何使用该命令以及一些优化技巧: 假设有一个名为 `page_view` 的日志表和另一个存储用户信息的 `users` 表。现在想要创建一个新的汇总表 `daily_user_activity` 来保存每天活跃用户的统计数据。 ```sql CREATE TABLE IF NOT EXISTS daily_user_activity ( userid STRING, activity_date DATE, count INT ); -- 插入当天活动量统计到每日用户活动中 INSERT OVERWRITE TABLE daily_user_activity SELECT u.id AS userid, pv.date AS activity_date, COUNT(*) AS count FROM users u JOIN page_view pv ON (u.id = pv.userid AND pv.date = '2008-03-03') GROUP BY u.id, pv.date; ``` 这段 SQL 查询首先通过内联接获取指定日期内的页面浏览记录及其对应的用户 ID ,接着按天分组计算每个用户的访问次数最后将这些聚合后的结果存入 `daily_user_activity` 表中。 对于只需要验证键存在性的场景,则可以采用左半连接 (`LEFT SEMI JOIN`) 方式提高效率[^2]: ```sql INSERT OVERWRITE TABLE active_users SELECT DISTINCT u.* FROM users u LEFT SEMI JOIN recent_logins rl ON (rl.user_id = u.id); ``` 这条语句的作用是从 `recent_logins` 表里筛选出最近登录过的那些用户并将它们的信息复制给 `active_users` 表。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值