You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过Synapse无服务器池OPENROWSET无法加载Parquet格式0001-01-01时间戳

问题根因

这个问题和DATETIME2类型本身的支持范围无关,本质是Azure Synapse无服务器SQL池的Parquet文件解析逻辑存在兼容性限制:

  • Spark默认写Parquet文件时,会用INT96类型存储时间戳,该类型的时间计算逻辑在Synapse无服务器池底层是基于1970-01-01的纪元偏移实现的,解析早于1970-01-01的时间时会出现整数溢出,无法正常映射到DATETIME2类型。
  • 即便把Parquet的时间存储格式改成TIMESTAMP_MILLIS/TIMESTAMP_MICROS,Synapse无服务器池目前对1900年之前的时间戳解析也存在未修复的缺陷,才会出现明明值在DATETIME2支持范围内却无法加载的报错。

可行解决方法

方案1:写入Parquet时预处理(推荐)

在Spark生成Parquet的阶段直接处理时间字段,从源头规避问题:

  • 方法A:将所有早于1970-01-01的时间戳统一转成字符串类型存储,后续读取后再做类型转换即可。
  • 方法B:对业务无影响的前提下,将0001-01-01这类极早的默认时间替换为1900-01-01等Synapse可正常解析的时间值,业务侧统一做逻辑兼容。

示例Spark修改代码:

from pyspark.sql.functions import to_timestamp, when, date_format, lit
dfx = (
    spark.createDataFrame(
        data = [ ("1","0001-01-01 00:00:00.000")],
        schema=["id","my_ts"])
    .withColumn("my_ts",to_timestamp("my_ts"))
    # 方案A:转字符串
    .withColumn("my_ts_str", date_format("my_ts", "yyyy-MM-dd HH:mm:ss.SSS"))
    # 方案B:替换极早时间
    .withColumn("my_ts_fixed", when(dfx.my_ts < lit("1900-01-01"), lit("1900-01-01 00:00:00.000").cast("timestamp")).otherwise(dfx.my_ts))
)

方案2:读取时绕开自动类型转换

如果无法修改源Parquet文件,可以在Synapse查询时指定schema,先把时间字段以字符串形式读取再手动转换:

SELECT
    id,
    TRY_CAST(my_ts_str AS DATETIME2(3)) AS my_ts
FROM
    OPENROWSET(
        BULK 'https://<MY-WORKSPACE>.dfs.core.windows.net/<MY-CONTAINER>/dfx/**',
        FORMAT = 'PARQUET',
        SCHEMA = (
            id VARCHAR(10),
            my_ts_str VARCHAR(30)
        )
    ) AS [result]

内容的提问来源于stack exchange,提问作者Anders Swanson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 11:36:02