【问题标题】:Databricks version 7.0 not behaving like version 6.3: class java.lang.Long cannot be cast to class java.lang.IntegerDatabricks 7.0 版的行为与 6.3 版不同:无法将类 java.lang.Long 强制转换为类 java.lang.Integer
【发布时间】:2020-10-11 00:09:19
【问题描述】:

我在 azure databricks 版本 6.3 - Spark 2.4.4 上有一个工作笔记本

此笔记本使用其连接器将数据引入 Azure Synapse Analytics

当我将笔记本升级到版本 7.0 - Spark 3.0.0 时,该过程开始失败并出现以下错误:

com.microsoft.sqlserver.jdbc.SQLServerException: HdfsBridge::recordReaderFillBuffer - 遇到意外错误 填充记录读取器缓冲区:ClassCastException:类 java.lang.Long 不能转换为 java.lang.Integer 类(java.lang.Long 和 java.lang.Integer 在加载器“bootstrap”的模块 java.base 中) [错误代码 = 106000] [SQLState = S0001]

这是 Synapse Analytics 中的表架构:

CREATE TABLE [dbo].[IncrementalDestination]
(
[Id] [int] NOT NULL,
[VarChar] [varchar](1000) NULL,
[Char] [char](1000) NULL,
[Text] [varchar](1000) NULL,
[NVarChar] [nvarchar](1000) NULL,
[NChar] [nchar](1000) NULL,
[NText] [nvarchar](1000) NULL,
[Date] [date] NULL,
[Datetime] [datetime] NULL,
[Datetime2] [datetime2](7) NULL,
[Smalldatetime] [smalldatetime] NULL,
[Bigint] [bigint] NULL,
[Bit] [bit] NULL,
[Decimal] [decimal](18, 0) NULL,
[Int] [int] NULL,
[Money] [money] NULL,
[Numeric] [numeric](18, 0) NULL,
[Smallint] [smallint] NULL,
[Smallmoney] [smallmoney] NULL,
[Tinyint] [tinyint] NULL,
[Float] [float] NULL,
[Real] [real] NULL,
[Column With Space] [varchar](1000) NULL,
[Column_ç_$pecial_char] [varchar](1000) NULL,
[InsertionDateUTC] [datetime] NOT NULL,
[De_LastUpdated] [datetime2](3) NOT NULL
)
WITH
(
DISTRIBUTION = ROUND_ROBIN,
CLUSTERED COLUMNSTORE INDEX
)
GO

这是 Databricks 在读取 Azure BlobStorage 中的一堆拼花后生成的架构

root
 |-- Id: long (nullable = true)
 |-- VarChar: string (nullable = true)
 |-- Char: string (nullable = true)
 |-- Text: string (nullable = true)
 |-- NVarChar: string (nullable = true)
 |-- NChar: string (nullable = true)
 |-- NText: string (nullable = true)
 |-- Date: timestamp (nullable = true)
 |-- Datetime: timestamp (nullable = true)
 |-- Datetime2: timestamp (nullable = true)
 |-- Smalldatetime: timestamp (nullable = true)
 |-- Bigint: long (nullable = true)
 |-- Bit: boolean (nullable = true)
 |-- Decimal: long (nullable = true)
 |-- Int: long (nullable = true)
 |-- Money: double (nullable = true)
 |-- Numeric: long (nullable = true)
 |-- Smallint: long (nullable = true)
 |-- Smallmoney: double (nullable = true)
 |-- Tinyint: long (nullable = true)
 |-- Float: double (nullable = true)
 |-- Real: double (nullable = true)
 |-- Column_With_Space: string (nullable = true)
 |-- Column_ç_$pecial_char: string (nullable = true)
 |-- InsertionDateUTC: timestamp (nullable = true)
 |-- De_LastUpdated: timestamp (nullable = false)

我看到了

Int: long (nullable = true)

但是我能做什么呢?

这种转换不应该是自然而轻松的吗?

我认为这些新功能有些问题=]

【问题讨论】:

    标签: azure-databricks azure-sql-data-warehouse azure-synapse


    【解决方案1】:

    我认为这是由以下更改引起的,如described in migration guide

    在 Spark 3.0 中,将值插入到具有不同数据类型的表列中时,将按照 ANSI SQL 标准执行类型强制。不允许某些不合理的类型转换,例如将 string 转换为 int 并将 double 转换为 boolean。 如果值超出列的数据类型范围,则会引发运行时异常。 在 Spark 2.4 及更低版本中,只要是有效的 Cast 就允许在表插入期间进行类型转换.将超出范围的值插入整数字段时,将插入该值的低位(与 Java/Scala 数字类型转换相同)。例如,如果将 257 插入到字节类型的字段中,则结果为 1。行为由选项 spark.sql.storeAssignmentPolicy 控制,默认值为“ANSI”。将选项设置为“旧版”会恢复以前的行为。

    因此您可以尝试将spark.sql.storeAssignmentPolicy 设置为Legacy 并重新运行代码。

    【讨论】:

    • 看起来你找到了地面,但我很好奇,我的测试流程是:sqlserver table -> parquet -> databricks -> dw table。 sql server表和dw表是一样的。我看不出如何导致超出范围的异常
    • 我发现我的提取过程正在将 int 转换为 long,但遗憾的是 spark.conf.set("spark.sql.storeAssignmentPolicy", "Legacy") 没有工作
    猜你喜欢
    • 2021-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-20
    • 2019-12-19
    • 2023-03-04
    • 2014-05-05
    • 1970-01-01
    相关资源
    最近更新 更多