Spark中DecimalType数值合规却报精度超出最大值问题排查
Spark DecimalType 转换报错:精度超过最大值38
我编写了如下代码:
spark = ( SparkSession.builder .appName("pyspark-sandbox") .getOrCreate() ) spark.conf.set("spark.sql.parquet.outputTimestampType", "TIMESTAMP_MICROS") # type: ignore faker = Faker() value = faker.pydecimal(left_digits=28, right_digits=10) print(value) # 8824750032877062776842530687.8719544506 df = spark.createDataFrame([[value]], schema=['DecimalItem']) df = df.withColumn('DecimalItem', col('DecimalItem').cast(DecimalType(38, 10))) df.show()
执行df.show()时抛出错误:
org.apache.spark.SparkArithmeticException: [DECIMAL_PRECISION_EXCEEDS_MAX_PRECISION] Decimal precision 46 exceeds max precision 38.
数值8824750032877062776842530687.8719544506看起来符合DecimalType(38, 10)的规格,却执行失败,请问问题出在哪里?
问题原因
- 调用
spark.createDataFrame([[value]], schema=['DecimalItem'])时,仅指定列名未明确数据类型,Spark会自动解析Python Decimal对象的内部精度。 - Faker生成的该Decimal对象的内部精度被Spark推断为46(超出Spark DecimalType的最大精度38),后续执行
cast(DecimalType(38,10))时,无法将高精度Decimal直接向下转换,触发精度超限错误。
解决方案
方案1:创建DataFrame时直接指定schema(推荐)
在创建DataFrame阶段就明确指定DecimalType(38,10),跳过自动推断步骤:
from pyspark.sql.types import StructType, StructField, DecimalType spark = ( SparkSession.builder .appName("pyspark-sandbox") .getOrCreate() ) spark.conf.set("spark.sql.parquet.outputTimestampType", "TIMESTAMP_MICROS") # type: ignore faker = Faker() value = faker.pydecimal(left_digits=28, right_digits=10) print(value) # 直接指定schema df = spark.createDataFrame( [[value]], schema=StructType([StructField('DecimalItem', DecimalType(38, 10))]) ) df.show()
方案2:先转字符串再转换类型
如果无法提前指定schema,可以先将Decimal转为字符串,再cast为目标类型:
df = spark.createDataFrame([[str(value)]], schema=['DecimalItem']) df = df.withColumn('DecimalItem', col('DecimalItem').cast(DecimalType(38, 10))) df.show()
内容的提问来源于stack exchange,提问作者lapots
相关产品推荐
相关产品推荐

