一、.hive-staging_hive 產生的原因:
通過spark-sql、hive-sql、hue等提交select或者insert overwrite等sql到hive時,會產生該目錄,用於臨時存放執行結果,比如insert overwrite會將結果暫存到該目錄下,待任務結束,將結果復制到hive表中。hql任務執行失敗時,這些臨時文件和目錄不會被自動刪除掉,直到有相關的hql執行成功時,才會自動刪掉。
二、.hive-staging_hive 會導致的一些問題:
1、如果目標路徑存在臨時文件的話,datax 讀取hdfs數據的時候會報錯,因為 .hive-staging_hive 臨時文件的數據也會被 datax 讀到;
2、有的 .hive-staging_hive 可能會包含很多的臨時文件,占用空間,同時也會造成 namenode 的壓力;
三、解決辦法(CDH):
進入hive配置頁面,搜索 hive-site.xml ,找到服務高級配置代碼段(安全閥)和 客戶端高級配置代碼段(安全閥),增加配置:
<property> <name>hive.insert.into.multilevel.dirs</name> <value>true</value> <description>允許生成多級目錄</description> </property> <property> <name>hive.exec.stagingdir</name> <value>/tmp/hive/staging/.hive-staging</value> <description>臨時文件暫放目錄</description> </property>
1、hive-site.xml 的 Hive 服務高級配置代碼段(安全閥)
2、hive-site.xml 的 Hive 客戶端高級配置代碼段(安全閥)
四、歷史遺留的 hive-staging 文件處理和定期維護
這邊提供一個 python3.6 腳本,需要注意的是刪除的時候,一般不要刪除今天的臨時文件,因為可能有作業正在使用。
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # @Time : 2020/5/7 09:59 # @Author : way # @Site : # @Describe: 清除hive昨日殘留的staging垃圾文件 import time import datetime from hdfs import Client class staging: def __init__(self, HDFS_ClIENT): """ :param HDFS_ClIENT: hdfs客戶端連接 """ self.client = Client(HDFS_ClIENT) self.today_timestamp = int(time.mktime(time.strptime(str(datetime.date.today()), '%Y-%m-%d')))*1000 # 移動 hive 垃圾文件 foo >> staging_tmp_path def move(self, foo, staging_tmp_path): filemsg = self.client.status(foo, strict=False) if filemsg.get('type') == 'DIRECTORY': dirs = self.client.list(foo, status=False) for son in dirs: if '.hive-staging_hive' in son: src = f'{foo}/{son}' dst = f'{staging_tmp_path}/{son}' # print(src, dst) self.client.rename(src, dst) print(f"{son} has moved to {dst} success") else: self.move(foo + '/' + son, staging_tmp_path) # 移除 昨天的垃圾文件 def delete(self, staging_tmp_path): dirs = self.client.list(staging_tmp_path, status=False) for dir in dirs: target = staging_tmp_path + '/' + dir modificationTime = self.client.status(target, strict=False).get('modificationTime') if '.hive-staging_hive' in dir and modificationTime < self.today_timestamp: # print(target) self.client.delete(target, recursive=True) print(f"{target} has been deleted success") if __name__ == "__main__": HDFS_ClIENT = "http://172.16.122.21:50070;http://172.16.122.24:50070" staging_tmp_path = '/tmp/hive/staging' stag = staging(HDFS_ClIENT) # 移動 hive 垃圾文件 foo >> staging_tmp_path # foo = '/user/hive/warehouse' # stag.move(foo, staging_tmp_path) # 移除 昨天的垃圾文件 stag.delete(staging_tmp_path)