工作中有一张表,非常大,没那么常用,但有时又得用,是增量更新的。只是增量方式有点独特。
hdfs目录下,叫A表吧,hdfs路径假如是/user/xxx/A/,每天是append写入这个目录下,这个目录下全是parquet文件。
(其实这个表其他库有这样增量的,/user/yyy/A/yyyyMMdd/,这是正常的。但是大约20个库,我得让上游整改,另一个表也有差不多情况,但明显数据量少一点,我先自己想想办法了)
如果我只想要把昨天日期的数据写入另一个地方,那么我要
spark.read.load("/user/xxx/A").where("dt=date_sub(current_date(),1)").write.mode("overwrite").save(另一个地方)
但是我看了下,这个库这个表每天的数据大约200MB,总文件量少说100G了。每次从这个总量里捞出昨天的数据,大海捞针啊,关键这么个小小操作,要跑1.5小时,不能凑合了…
解决方案:
from py4j.java_gateway import java_import
from datetime import datetime,timezone
java_import(spark._jvm,"org.apache.hadoop.fs.Path")
java_import(spark._jvm,"org.apache.hadoop.fs.FileSystem")
file_path="/user/xxx/A" #你的路径
fs=spark._jvm.FileSystem.get(spark._jsc.hadoopConfiguation())
path=spark._jvm.Path(file_path)
status=fs.listStatus(path)
for file_status in status:
modification_time=file_status.getModificationTime()
modified_time=datetime.fromtimestamp(modification_time/1000).strftime("%Y-%m-%d") #,tz=timezone.utc
file_path=file_status.getPath()
file_name=file_path.getName()
print(file_name,modified_time)
这样我就可以只读取今天更新的文件了(是昨天的内容,T+1)
file_path="/user/xxx/A" #你的路径
today_format=datetime.today().strftime("%Y-%m-%d")
file_names=[]
for file_status in status:
modification_time=file_status.getModificationTime()
modified_time=datetime.fromtimestamp(modification_time/1000).strftime("%Y-%m-%d") # ,tz=timezone.utc
if modified_time==today_format:
file_path=file_status.getPath()
file_name=file_path.getName()
file_names.append(file_name)
file_names_=",".join(file_names)
spark.read.load("%s/{%s}"%(file_path,file_names_)).write.mode("overwrite").save(另一个地方)
经过改造后,执行时间3分钟!!!
这样就可以啦(每天不出意外的情况下) 😼