Insert Overwrite 进行hive或impala小文件合并后 文件数量不是1

本文探讨了HDFS中因大量小文件导致的性能下降问题,通过调整Hive和Impala参数实现小文件合并,包括设置reduce任务数量和启用文件合并功能,确保输出单一文件,提升系统效率。

HDFS的表里面,按天分区,每个分区都有很多的小文件,长此以往必然会导致性能的下降。所以我们在保持原来的业务逻辑不变,增加每日跑批 来合并分区内的小文件。

刚开始我是直接Impala执行Insert overwrite ,想合并某一天分区内的4份文件, 发现分区内部的文件数还是4个,我就纳闷,以为我记错了 overwrite 的执行原理,然后使用Hive 进行 insert overwrite,结果文件数变成了2个,我就纳闷了。。
然后想到可能是因为写线程的问题。于是网上搜怎么配置这些参数,问题就解决了。Impala 的那个配置是从官网挨个实验的,当然,这些设置会影响执行sql的性能,但是能保证只生成一份文件,怎么取舍自己考虑。

Hive 的方法:

set mapred.reduce.tasks=1;
set hive.merge.mapredfiles=true;
insert overwrite table xx.xxx
partition (year=2020,month=4,day=1)
select
	fields...
from xx.xxx
where year=2020
and month=4
and day=3

set mapred.reduce.tasks=1;
set hive.merge.mapredfiles=true;
增加这两个配置是为了保持输出的文件只有一个。为什么要这么配置可以想想MapReduce 的原理,我们要保证最后只有一个reduce。

Impala 同样,但是需要设置的参数有点不同,还有sql 的写法也略有差异

set NUM_NODES=1;

insert overwrite xx.xx(
    	fields...
)
partition (idn_year={idn_year},idn_month={idn_month},idn_day={idn_day})
    select 
    	fields...
from x.xx
where 
    idn_year={idn_year} 
    and idn_month={idn_month}
    and idn_day={idn_day}

set NUM_NODES=1;
了解Impala原理的都知道,Impala是有执行器和接收器的,默认情况这个参数是0,即所有节点一起跑,并行执行任务,设置为1后,就是接收器单节点跑,结果很明显,并行跑的很多会有多个文件,单节点才能保证只有一个文件。

注意:
这些参数的设置不是都是死的,你要根据自己的表的内容的增量来判断,到底是合并为一份文件,还是多少份文件比较合适,毕竟还是要尽量配合128M的嘛。

在SQL中,`INSERT OVERWRITE` 是一种用于覆盖表分区数据的语法,但它的支持情况取决于具体的数据库系统。以下是不同数据库中关于覆盖入(`INSERT OVERWRITE`)的说明和替代方案: --- ### **1. 支持 `INSERT OVERWRITE` 的数据库** #### **Hive / Spark SQL** - **语法**: ```sql INSERT OVERWRITE TABLE 表名 [PARTITION (分区列='值')] SELECT 列1, 列2, ... FROM 源表; ``` - **作用**:直接覆盖目标表分区的全部数据。 - **示例**: ```sql -- 覆盖整个表 INSERT OVERWRITE TABLE employee SELECT * FROM temp_employee; -- 覆盖指定分区 INSERT OVERWRITE TABLE sales PARTITION (year=2023) SELECT product, amount FROM sales_2023; ``` #### **Impala** - 语法与Hive类似,支持覆盖入表分区。 --- ### **2. 不支持 `INSERT OVERWRITE` 的数据库及替代方案** #### **MySQL / PostgreSQL / SQL Server / Oracle** 这些数据库**不直接支持** `INSERT OVERWRITE`,但可以通过以下方式实现类似效果: ##### **方法1:先删除数据,再插入** ```sql -- 删除表数据(清空表) TRUNCATE TABLE 表名; -- 推荐(速度快,不记录日志) -- DELETE FROM 表名; -- 慢,但可带条件删除 -- 插入新数据 INSERT INTO 表名 (列1, 列2) SELECT 列1, 列2 FROM 源表; ``` ##### **方法2:使用 `REPLACE`(MySQL特有)** ```sql -- 替换已存在的行(基于主键唯一键) REPLACE INTO 表名 (列1, 列2) SELECT 列1, 列2 FROM 源表; ``` ##### **方法3:使用 `MERGE`(Oracle / SQL Server / PostgreSQL)** ```sql -- Oracle示例 MERGE INTO 目标表 t USING 源表 s ON (t.主键 = s.主键) WHEN MATCHED THEN UPDATE SET t.列1 = s.列1, t.列2 = s.列2 WHEN NOT MATCHED THEN INSERT (列1, 列2) VALUES (s.列1, s.列2); ``` ##### **方法4:创建临时表替换原表** ```sql -- 1. 创建临时表并插入数据 CREATE TABLE 临时表 AS SELECT * FROM 源表; -- 2. 删除原表 DROP TABLE 原表; -- 3. 重命名临时表为原表名 ALTER TABLE 临时表 RENAME TO 原表; ``` --- ### **3. 注意事项** 1. **权限要求**:覆盖操作通常需要 `DROP`、`CREATE` `TRUNCATE` 权限。 2. **事务安全**:在生产环境中,建议使用事务确保操作原子性。 ```sql BEGIN TRANSACTION; TRUNCATE TABLE 表名; INSERT INTO 表名 SELECT * FROM 源表; COMMIT; ``` 3. **分区表**:如果表是分区的,建议仅覆盖需要的分区以减少性能开销。 4. **备份数据**:覆盖前务必备份,避免误操作导致数据丢失。 --- ### **为什么 `INSERT OVERWRITE` 不通用?** - **设计差异**:传统关系型数据库(如MySQL)更倾向于显式控制数据修改(如 `DELETE` + `INSERT`),而Hive等大数据工具优化了批量覆盖场景。 - **事务支持**:`INSERT OVERWRITE` 在Hive中是原子操作,但MySQL等数据库通过事务实现类似效果。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值