Hive 从spark查询拼花地板表上的配置单元时,十进制值已损坏

Hive 从spark查询拼花地板表上的配置单元时,十进制值已损坏,hive,apache-spark-sql,parquet,cloudera-cdh,Hive,Apache Spark Sql,Parquet,Cloudera Cdh,使用Spark SQL在Spark代码中查询拼花地板上的外部配置单元表时,Spark返回十进制字段的垃圾值/不正确值 在我的应用程序流中,spark进程最初将数据直接写入这些拼花地板文件,并将其写入存在外部配置单元表的HDF中。当第二个Spark进程试图使用Spark SQL从配置单元表中使用数据时,获取的数据不正确 场景步骤:这是一个简单的演示,再现了问题: 写入拼花:我正在HDFS中将数据写入拼花文件,Spark本身假设十进制字段的精度为小数点28,26 读取拼花文件:查看值是否正确写入 s

使用Spark SQL在Spark代码中查询拼花地板上的外部配置单元表时,Spark返回十进制字段的垃圾值/不正确值

在我的应用程序流中,spark进程最初将数据直接写入这些拼花地板文件,并将其写入存在外部配置单元表的HDF中。当第二个Spark进程试图使用Spark SQL从配置单元表中使用数据时,获取的数据不正确

场景步骤:这是一个简单的演示,再现了问题:

写入拼花:我正在HDFS中将数据写入拼花文件,Spark本身假设十进制字段的精度为小数点28,26

读取拼花文件:查看值是否正确写入

scala> val df_parq = spark.read.option("spark.sql.decimalOperations.allowPrecisionLoss",false).parquet("/tenants/gwm/morph/test/tablePrecisionTest/test")
df_parq: org.apache.spark.sql.DataFrame = [name: string, value: decimal(28,26)]
scala> df_parq.show
+-------+--------------------+
|   name|               value|
+-------+--------------------+
|  dummy|10.70000000000000...|
+-------+--------------------+ 
创建外部蜂巢表:位于拼花地板位置的顶部,十进制字段为小数点18,6

以直线方式运行配置单元查询:以验证返回的数据是否正确

hive> select * from db1.test_precision;
+----------------------+-----------------------+--+
| test_precision.name  | test_precision.value  |
+----------------------+-----------------------+--+
| dummy                | 10.7                  |
+----------------------+-----------------------+--+
使用Spark Sql运行相同的查询:生成的十进制值不正确

scala> val df_hive = spark.sql("select * from db1.test_precision")
df_hive: org.apache.spark.sql.DataFrame = [name: string, value: decimal(18,6)]
scala> df_hive.show
+-----+-----------+
| name|      value|
+-----+-----------+
|dummy|-301.989888|
+-----+-----------+
注意-我知道在第一步将值显式存储为Decima18,6可以解决问题,但我已经有了无法立即重新加载的历史数据


在第5步读取数值时,是否有办法解决此问题?

除了第3步,我完全复制了您的示例。为Decimal类型创建表格时,应保持精度和比例

在您的例子中,您创建了一个小数28,26

df:org.apache.spark.sql.DataFrame=[名称:字符串,值:小数点28,26] 因此,您应该为decimal类型创建一个具有相同精度和比例的表

hive> CREATE EXTERNAL TABLE test.test_precision(name string, value Decimal(28,26)) STORED AS PARQUET LOCATION 'hdfs://quickstart.cloudera:8020/user/cloudera/test_decimal';
/**AND NOT**/
hive> create external table db1.test_precision(name string, value Decimal(18,6)) STORED As PARQUET LOCATION '/my/hdfs/location/test';
scala>val df=spark.sqlselect'dummy'作为名称,10.700000000000000000作为值 df:org.apache.spark.sql.DataFrame=[名称:字符串,值:小数点28,26] scala>df.show +---+----------+ |名称|值| +---+----------+ |虚拟| 10.7000000000000| +---+----------+ scala>df.printSchema 根 |-名称:string nullable=false |-值:小数点28,26可为空=false scala>df.write.optionoverwrite,true.parquethdfs://quickstart.cloudera:8020/user/cloudera/test_decimal scala>val df_parq=spark.read.optionspark.sql.decimalOperations.allowPrecisionLoss,false.parquethdfs://quickstart.cloudera:8020/user/cloudera/test_decimal df_parq:org.apache.spark.sql.DataFrame=[名称:字符串,值:小数点28,26] scala>df_parq.printSchema 根 |-名称:string nullable=true |-值:小数点28,26可为空=真 scala>df_parq.show +---+----------+ |名称|值| +---+----------+ |虚拟| 10.7000000000000| +---+----------+ 配置单元>创建外部表test.test_precisionname字符串,值小数28,26存储为拼花地板位置'hdfs://quickstart.cloudera:8020/user/cloudera/test_decimal'; 蜂巢>从测试精度中选择*; +-----------+------------+-+ |test_precision.name | test_precision.value| +-----------+------------+-+ |假人| 10.7| +-----------+------------+-+ scala>val df_hive=spark.sqlselect*from test.test_precision df_hive:org.apache.spark.sql.DataFrame=[名称:字符串,值:小数点28,26] scala>df_hive.show +---+----------+ |名称|值| +---+----------+ |虚拟| 10.7000000000000| +---+----------+ scala>df_hive.printSchema 根 |-名称:string nullable=true |-值:小数点28,26可为空=真
scala> val df_hive = spark.sql("select * from db1.test_precision")
df_hive: org.apache.spark.sql.DataFrame = [name: string, value: decimal(18,6)]
scala> df_hive.show
+-----+-----------+
| name|      value|
+-----+-----------+
|dummy|-301.989888|
+-----+-----------+
hive> CREATE EXTERNAL TABLE test.test_precision(name string, value Decimal(28,26)) STORED AS PARQUET LOCATION 'hdfs://quickstart.cloudera:8020/user/cloudera/test_decimal';
/**AND NOT**/
hive> create external table db1.test_precision(name string, value Decimal(18,6)) STORED As PARQUET LOCATION '/my/hdfs/location/test';