【问题标题】:Polybase from Parquet error: Cannot cast Java.lang.Double to来自 Parquet 错误的 Polybase:无法将 Java.lang.Double 转换为
【发布时间】:2019-09-07 21:35:30
【问题描述】:

通过 Polybase 加载 Azure 数据仓库,我正在读取 Azure Blob 上的 Parquet 文件。

首先我在 SQL 中创建了一个外部表来指向 Parquet 文件,然后使用 CTAS 加载。无论我在 SQL 中使用什么数据类型,它都会给我这种类型转换错误。我试过 DECIMAL、NUMERIC、FLOAT。但加载 VARCHAR 工作正常。

我怀疑这与 Parquet 文件的创建方式有关,该文件来自 Python Pandas 数据框,使用 df.to_parquetpyarrow。深入研究源代码并进行实验,我发现在 Arrow(Parquet 之前的步骤)中的数据类型数据是 Double。也许这就是为什么?

另外,我在创建文件时尝试了 Gzip 和 Snappy 作为压缩类型,在创建 SQL 外部表时,没有骰子。

因此而发疯。有什么想法吗?

重现步骤

环境:

conda create -n testenv python=3.6

conda install -n testenv -c conda-forge pyarrow

conda list -n testenv

# Name                    Version                   Build  Channel
arrow-cpp                 0.13.0           py36hee3af98_1    conda-forge
boost-cpp                 1.68.0            h6a4c333_1000    conda-forge
brotli                    1.0.7             he025d50_1000    conda-forge
ca-certificates           2019.3.9             hecc5488_0    conda-forge
certifi                   2019.3.9                 py36_0    conda-forge
gflags                    2.2.2             he025d50_1001    conda-forge
glog                      0.3.5                h6538335_1
intel-openmp              2019.3                      203
libblas                   3.8.0                     5_mkl    conda-forge
libcblas                  3.8.0                     5_mkl    conda-forge
liblapack                 3.8.0                     5_mkl    conda-forge
libprotobuf               3.7.1                h1a1b453_0    conda-forge
lz4-c                     1.8.1.2              h2fa13f4_0
mkl                       2019.3                      203
numpy                     1.16.2           py36h8078771_1    conda-forge
openssl                   1.1.1b               hfa6e2cd_2    conda-forge
pandas                    0.24.2           py36h6538335_0    conda-forge
parquet-cpp               1.5.1                         2    conda-forge
pip                       19.0.3                   py36_0
pyarrow                   0.13.0           py36h8c67754_0    conda-forge
python                    3.6.8                h9f7ef89_7
python-dateutil           2.8.0                      py_0    conda-forge
pytz                      2019.1                     py_0    conda-forge
re2                       2019.04.01       vc14h6538335_0  [vc14]  conda-forge
setuptools                41.0.0                   py36_0
six                       1.12.0                py36_1000    conda-forge
snappy                    1.1.7             h6538335_1002    conda-forge
sqlite                    3.27.2               he774522_0
thrift-cpp                0.12.0            h59828bf_1002    conda-forge
vc                        14.1                 h0510ff6_4
vs2015_runtime            14.15.26706          h3a45250_0
wheel                     0.33.1                   py36_0
wincertstore              0.2              py36h7fe50ca_0
zlib                      1.2.11            h2fa13f4_1004    conda-forge
zstd                      1.3.3                    vc14_1    conda-forge

Python:

>>> import pandas as pd
>>> df = pd.DataFrame({'ticker':['AAPL','AAPL','AAPL'],'price':[101,102,103]})
>>> df
  ticker  price
0   AAPL    101
1   AAPL    102
2   AAPL    103
>>> df.to_parquet('C:/aapl_test.parquet',engine='pyarrow',compression='snappy',index=False)

Azure 步骤:

  1. 已将 Parquet 文件上传到 Azure Blob
  2. 使用 Azure 数据仓库 Gen2,大小:DW400c
  3. 根据docstutorial,创建了数据库范围凭据、外部数据源和外部文件格式

SQL 代码:

CREATE EXTERNAL FILE FORMAT [ParquetFileSnappy] WITH (
    FORMAT_TYPE = PARQUET, 
    DATA_COMPRESSION = N'org.apache.hadoop.io.compress.SnappyCodec'
)
GO

CREATE EXTERNAL DATA SOURCE [AzureBlobStorage] WITH (
    TYPE = HADOOP, 
    LOCATION = N'wasbs://[redacted: containerName]@[redacted: storageAccountName].blob.core.windows.net', 
    CREDENTIAL = [AzureQuantBlobStorageCredential] -- created earlier
)
GO

CREATE EXTERNAL TABLE ext.technicals(
    [ticker] VARCHAR(5) NOT NULL ,
    [close_px] DECIMAL(8,2) NULL
) WITH (
    LOCATION='/aapl_test.parquet', 
    DATA_SOURCE=AzureBlobStorage, 
    FILE_FORMAT=ParquetFileSnappy 
);

CREATE TABLE [dbo].TechnicalFeatures
WITH
( 
    DISTRIBUTION = ROUND_ROBIN,
    CLUSTERED COLUMNSTORE INDEX
)
AS SELECT * FROM [ext].technicals
OPTION (LABEL = 'CTAS : Load [dbo].[TechnicalFeatures]')
;

这是错误:

Msg 106000, Level 16, State 1, Line 20
HdfsBridge::recordReaderFillBuffer - Unexpected error encountered filling record reader buffer: ClassCastException: class java.lang.Long cannot be cast to class parquet.io.api.Binary (java.lang.Long is in module java.base of loader 'bootstrap'; parquet.io.api.Binary is in unnamed module of loader 'app')

编辑: 还尝试使用fastparquet 而不是pyarrow,同样的错误。

【问题讨论】:

  • @wesm 这是 pyarrow 的错误吗?
  • 请详细说明以下 CREATE EXTERNAL DATA SOURCE T-SQL 你可以在它说的地方: DATA_SOURCE=AzureBlobStorage, -- 我之前创建的 FILE_FORMAT=ParquetFileSnappy -- 我之前创建的
  • @MikeUbezziMSFT 刚刚使用其他 SQL sn-ps 更新了示例
  • 仅更改并重新运行:TYPE = HADOOPTYPE = BLOB_STORAGECREATE EXTERNAL DATA SOURCE
  • Parse error at line: 3, column: 9: Incorrect syntax near 'BLOB_STORAGE'. 不起作用

标签: pandas parquet azure-sqldw pyarrow polybase


【解决方案1】:

我重复了你的 Python 文件创建...你欠我一杯啤酒,因为 Anaconda 安装造成的痛苦和折磨;)

在使用 parquet-tools 检查文件时,问题是您的数据值被写入为长整数 (101,102,103),但您试图在 Create External Table 语句中将它们映射为小数。

如果您将 DECIMAL(8,2) 更改为 BIGINT,则将加载您的数据。

或者,通过添加小数点(101.0、102.0、103.0)将数据值写入双精度值,然后您可以通过将 DECIMAL(8,2) 更改为 DOUBLE PRECISION 甚至 FLOAT 来读取它们,因为它们小而精确本例中的数字。

(开啤酒的玩笑)

【讨论】:

  • 顺便说一下,我刚刚测试过 Parquet-tools 的替代品,发现效果很好。 Parquet.Net 项目有一个名为 PARQ 的实用程序。它是 .Net Core,因此它应该可以在 Windows、Linux 和 OSX 上运行。查看 Parquet 文件架构的命令是“parq schema path-to-file”。 github.com/elastacloud/parquet-dotnet/blob/master/doc/parq.md
猜你喜欢
  • 2023-01-22
  • 1970-01-01
  • 2021-01-30
  • 2023-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-01
  • 2022-10-25
相关资源
最近更新 更多