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
相关产品推荐
相关产品推荐

