Spark 1.6.0视图中无法使用input_file_name()函数的问题咨询
这是Spark 1.6.x版本的已知限制,不是你的操作有误,我来给你拆解一下原因和可行的解决办法:
核心原因
input_file_name()属于Spark的数据源元数据函数,它的工作依赖于直接读取数据源时的上下文信息——只有在你直接从文件系统读取数据的DataFrame操作中(比如spark.read之后的select或withColumn),Spark才能获取到每个分区对应的文件路径。
而视图(不管是Spark临时视图还是Hive中创建的视图)本质上是一段保存下来的逻辑查询计划,它不会关联原始数据源的上下文。当你查询视图时,Spark只会解析视图的逻辑计划,无法回溯到最初的数据源去获取文件元数据,所以会抛出"未知函数"的错误。
至于INPUT__FILE__NAME,这是Hive的内置虚拟变量,但Spark 1.6.x对Hive的兼容性还比较有限,尤其是在视图场景下,Spark并不会将这个Hive变量解析为对应的文件路径,因此同样无法生效。
可行的替代方案
方案1:读取数据时提前添加文件路径列
这是最可靠的解决方式,在读取数据源的第一步就把文件路径作为列添加进去,再基于这个带路径的DataFrame创建视图:
// 读取数据时直接添加文件路径列 val rawDF = spark.read.text("/your/data/path").withColumn("file_path", input_file_name()) // 创建包含路径列的视图 rawDF.createOrReplaceTempView("data_with_file_path")
之后你查询这个视图时,就能正常使用file_path列获取文件路径了。
方案2:针对Hive表的补充尝试(不推荐)
如果你的数据是Hive表,可以尝试在Hive中给表添加虚拟列:
ALTER TABLE your_hive_table ADD COLUMNS (input_file_name STRING);
但Spark 1.6.x对Hive虚拟列的支持并不完善,大概率还是无法正常获取路径,所以优先推荐方案1。
版本升级建议
如果后续有条件升级到Spark 2.x及以上版本,这个场景的兼容性会有明显改善——Spark 2.x开始优化了视图的上下文保留逻辑,部分场景下可以直接在视图中使用这类元数据函数,但从稳定性角度来说,还是建议在读取数据时就提前添加路径列,避免依赖版本特性带来的不确定性。
内容的提问来源于stack exchange,提问作者Joha

