Spark SQL读取Apache Phoenix表时timestamp毫秒位显示不一致问题
问题原因
该问题是Spark原生Timestamp类型的序列化输出规则导致的:Spark在将Timestamp类型转为字符串输出时,会自动省略毫秒位末尾的0,而Phoenix原生查询默认统一将毫秒位补零到3位,二者展示规则不一致,数据本身的毫秒精度并没有丢失。
解决方案
方案1:仅格式化指定查询结果的展示格式
如果只需要当前查询的EVENT_TIME字段输出统一3位毫秒,无需改动全局配置,直接使用Spark内置的date_format函数格式化字段即可,Java代码示例如下:
import org.apache.spark.sql.functions; DataFrame result = sqlContext.read().format("org.apache.phoenix.spark").jdbc(zkUrl, sql, new Properties()); // 将EVENT_TIME字段格式化为固定带3位毫秒的字符串 DataFrame formattedRes = result.withColumn("EVENT_TIME", functions.date_format(functions.col("EVENT_TIME"), "yyyy-MM-dd HH:mm:ss.SSS") ); formattedRes.show(100);
方案2:全局配置Spark Timestamp输出格式
如果需要所有Spark任务的Timestamp类型都默认输出3位毫秒格式,在初始化SparkSession时添加以下两个配置即可:
SparkSession spark = SparkSession.builder() .appName("PhoenixDataExtract") // 启用Java8时间API,优化时间类型序列化逻辑 .config("spark.sql.datetime.java8API.enabled", "true") // 全局指定Timestamp的默认输出格式,固定3位毫秒 .config("spark.sql.timestampFormat", "yyyy-MM-dd HH:mm:ss.SSS") .getOrCreate();
配置生效后,所有Timestamp类型字段的toString输出、show()展示都会自动补零到3位毫秒,无需逐个字段格式化。
方案3:写入外部存储时统一格式
如果是需要将结果写入文件、数据库等外部存储时保持3位毫秒格式,除了上述全局配置外,也可以在写入逻辑中指定对应格式参数即可。
内容的提问来源于stack exchange,提问作者Omegaspard
相关产品推荐
相关产品推荐

