十进制数据类型无法在 spark 和 Hive 中正确存储值

Posted

技术标签:

【中文标题】十进制数据类型无法在 spark 和 Hive 中正确存储值【英文标题】:Decimal data type not storing the values correctly in both spark and Hive 【发布时间】:2016-02-04 19:01:16 【问题描述】:

我在存储十进制数据类型时遇到问题,不确定是错误还是我做错了什么

文件中的数据是这样的

Column1 column2 column3
steve   100     100.23
ronald  500     20.369
maria   600     19.23

当我使用 csv 阅读器推断 spark 中的模式时,它将 column3 的数据类型作为字符串,因此我将其转换为十进制并将其保存为表。

现在当我访问表格时,它以以下方式显示输出,消除了小数

Column1 column2 column3
steve   100     100
ronald  500     20
maria   600     19

我还在 Hive 中测试了同样的事情,方法是创建一个以 column3 为十进制的本地表,并用数据加载它,同样它没有将它们存储为十进制。

我们将不胜感激。

这是上面的代码

在 spark 文件的 schema

root
 |-- DEST_AIRPORT_ID: integer (nullable = true)
 |-- DEST_AIRPORT_SEQ_ID: integer (nullable = true)
 |-- DEST_CITY_MARKET_ID: integer (nullable = true)
 |-- DEST string: string (nullable = true)
 |-- DEST_CITY_NAME: string (nullable = true)
 |-- DEST_STATE_ABR: string (nullable = true)
 |-- DEST_STATE_FIPS: integer (nullable = true)
 |-- DEST_STATE_NM: string (nullable = true)
 |-- DEST_WAC: integer (nullable = true)
 |-- DEST_Miles: double (nullable = true)

代码

from pyspark import SparkContext
sc =SparkContext()

from pyspark.sql.types import *
from pyspark.sql import HiveContext
sqlContext = HiveContext(sc)

Data=sqlContext.read.format("com.databricks.spark.csv").options(header="true").options(delimiter=",").options(inferSchema="true").load("s3://testbucket/Data_test.csv")

Data1=Data.withColumnRenamed('DEST string','DEST_string')

Data2 =Data1.withColumn('DEST_Miles',Data1.DEST_Miles.cast('Decimal'))

Data2.saveAsTable('Testing_data', mode='overwrite',path='s3://bucketname/Testing_data')

转成十进制后的架构

root
 |-- DEST_AIRPORT_ID: integer (nullable = true)
 |-- DEST_AIRPORT_SEQ_ID: integer (nullable = true)
 |-- DEST_CITY_MARKET_ID: integer (nullable = true)
 |-- DEST string: string (nullable = true)
 |-- DEST_CITY_NAME: string (nullable = true)
 |-- DEST_STATE_ABR: string (nullable = true)
 |-- DEST_STATE_FIPS: integer (nullable = true)
 |-- DEST_STATE_NM: string (nullable = true)
 |-- DEST_WAC: integer (nullable = true)
 |-- DEST_Miles: decimal (nullable = true)

为了蜂巢

create table Destination(
        DEST_AIRPORT_ID int,
        DEST_AIRPORT_SEQ_ID int,
        DEST_CITY_MARKET_ID int,
        DEST string,
        DEST_CITY_NAME string,
        DEST_STATE_ABR string,
        DEST_STATE_FIPS string,
        DEST_STATE_NM string,
        DEST_WAC int,
        DEST_Miles Decimal(10,0)
      );
INSERT INTO TEST_DATA SELECT * FROM TESTING_data;  

如果您还需要更多信息,请告诉我。

谢谢 谢谢

【问题讨论】:

【参考方案1】:

DECIMAL 在 Hive V0.12 中的意思是“大浮点”。就像 Oracle 中的 NUMBER(38)。

但在后来的版本中发生了重大变化,DECIMAL 没有任何比例/精度规范现在意味着“一个大整数”。就像 Oracle 中的 NUMBER(10,0)。

参考

Hive language manual / data types 在 cwiki.apache.org 某处标记为“Hive 十进制精度/规模支持”的冗长 PDF 文档

底线:你必须明确定义多少位你想要,这正是几十年前ANSI SQL标准所期望的。例如,DECIMAL(15,3) 将容纳 12 位整数部分 + 3 位小数部分(即 15 位数字和任意位置的逗号)

【讨论】:

精度为 15 意味着整个数字总共只能有 15 位数字(整数和小数部分)。 “从 Hive 0.13 开始,用户可以在使用 DECIMAL(precision, scale) 语法创建具有 DECIMAL 数据类型的表时指定比例和精度。如果未指定比例,则默认为 0(无小数位)。如果未指定精度,它默认为 10。” cwiki.apache.org/confluence/display/Hive/…【参考方案2】:

对于 Decimal 类型,Spark 和 Hive 的默认精度为 10,小数位数为零。这意味着如果您不指定比例,则小数点后将没有数字。

【讨论】:

【参考方案3】:

该文件有不同的分隔符(我认为是制表符)并且您正在使用“,”读取文件。

是的,它转换为字符串,但您不应该丢失数据。试试这个:

>>> lines = spark.read.options( delimiter='\t', header='true').csv("/home/kiran/km/km_hadoop/data/data_tab_sep")
>>> lines.show()
+-------+-------+-------+
|Column1|column2|column3|
+-------+-------+-------+
|  steve|    100| 100.23|
| ronald|    500| 20.369|
|  maria|    600|  19.23|
+-------+-------+-------+

>>> lines.printSchema()
root
 |-- Column1: string (nullable = true)
 |-- column2: string (nullable = true)
 |-- column3: string (nullable = true)

您可以像下面这样转换为 DoubleType。 (注意:对于您的情况,您不需要它,因为您正在写信给 FS)

>>> from pyspark.sql.types import DoubleType
>>> lines.select(lines["column1"], lines["column2"], lines["column3"].cast(DoubleType())).printSchema()
root
 |-- column1: string (nullable = true)
 |-- column2: string (nullable = true)
 |-- column3: double (nullable = true)

【讨论】:

【参考方案4】:

我在从 oracle 读取数据时遇到了同样的问题,我可以通过强制转换来解决这个问题

joinedDF.col("START_EPOCH_TIME").cast("string") 

【讨论】:

以上是关于十进制数据类型无法在 spark 和 Hive 中正确存储值的主要内容,如果未能解决你的问题,请参考以下文章

将 Blob 数据类型存储在 Hive 表中的最佳方式是字符串还是二进制?

使用 Spark Scala 将 Sql Server 数据类型转换为 Hive 数据类型

Hive 二进制和字符串数据类型

Spark无法读取hive 3.x的表数据

数据分析EPHS(15)-Spark如何处理Hive的集合类型?

无法使用 Apache spark 2.1.0 连接到 hive 数据库