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

PySpark读取Oracle NUMBER类型时的Decimal精度问题求助

解决Spark读取Oracle NUMBER类型数据精度失真问题

问题原因

你遇到的精度失真,是因为Spark默认对Decimal类型的精度限制(默认spark.sql.decimal.maxPrecision为10,spark.sql.decimal.maxScale为0),无法匹配Oracle NUMBER类型的高精度存储。而spark.sql.decimalOperations.allowPrecisionLoss仅控制Decimal运算阶段是否允许精度损失,对数据读取阶段的类型推断没有作用。

解决方案

1. 显式指定自定义Schema读取

读取Oracle数据时,直接指定对应字段为DecimalType(38, N)(38是Oracle NUMBER的最大精度,N为字段实际小数位数),跳过Spark的自动类型推断:

from pyspark.sql.types import StructType, StructField, IntegerType, DecimalType

# 自定义Schema,根据Oracle字段实际小数位调整DecimalType的第二个参数
custom_schema = StructType([
    StructField("ID", IntegerType(), nullable=True),
    StructField("how_it_is_in_oracledb", DecimalType(38, 12), nullable=True)
])

# 读取Oracle数据
df = spark.read.format("jdbc") \
    .option("url", "jdbc:oracle:thin:@//your-oracle-host:port/service_name") \
    .option("dbtable", "your_target_table") \
    .option("user", "db_user") \
    .option("password", "db_password") \
    .schema(custom_schema) \
    .load()

2. 全局调整Spark Decimal精度配置

在Spark会话初始化时,设置全局Decimal的最大精度和小数位,让Spark支持Oracle NUMBER的高精度:

# 在创建SparkSession前或会话中设置
spark.conf.set("spark.sql.decimal.maxPrecision", 38)
spark.conf.set("spark.sql.decimal.maxScale", 18)

也可以在spark-defaults.conf中添加以下配置,全局生效:

spark.sql.decimal.maxPrecision 38
spark.sql.decimal.maxScale 18

3. 字符串中转后转换为Decimal(兜底方案)

如果前两种方法仍有问题,可以先将NUMBER字段以字符串类型读取,再转换为高精度Decimal:

from pyspark.sql.types import StructType, StructField, IntegerType, StringType
from pyspark.sql.functions import col

# 先按字符串读取
temp_schema = StructType([
    StructField("ID", IntegerType(), nullable=True),
    StructField("how_it_is_in_oracledb", StringType(), nullable=True)
])

temp_df = spark.read.format("jdbc") \
    .option("url", "jdbc:oracle:thin:@//your-oracle-host:port/service_name") \
    .option("dbtable", "your_target_table") \
    .option("user", "db_user") \
    .option("password", "db_password") \
    .schema(temp_schema) \
    .load()

# 转换为高精度Decimal
final_df = temp_df.withColumn("how_it_is_in_oracledb", col("how_it_is_in_oracledb").cast(DecimalType(38, 12)))

验证方法

读取后可以通过df.printSchema()查看字段类型,或用df.show(truncate=False)确认数据精度是否和Oracle一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 03:55:16