PySpark设置inferSchema=True时自动推断列类型的底层原理
Spark CSV 数据源
inferSchema参数运行逻辑 inferSchema是Spark读取CSV时的类型自动推导参数,默认值为false,开启后会额外扫描数据完成列类型判定,相关问题具体解答如下:
1. 是否会扫描全量CSV数据?
- 该行为和Spark版本强关联:早期Spark 1.x时代,CSV能力由第三方Databricks CSV包提供,开启
inferSchema时会扫描全量数据做类型判定;Spark 2.x版本将CSV数据源内置到官方模块后,默认不会扫描全量数据,走采样推导逻辑。 - 只有手动配置关闭采样、强制全量推导时才会遍历全表,这种场景类型推导准确率最高,但性能开销也最大。
2. 默认采样扫描行数是多少?
- 默认采样行数由配置项
spark.sql.csv.sampleSizeForInferring控制,默认值为1000行。采样逻辑会从所有输入数据分片(split)中按比例抽取行,凑够配置的采样行数,并非仅读取首个文件的前N行,尽可能降低单文件数据分布带来的采样偏差。 - 你可以在读取CSV时通过
option手动调整该参数,比如spark.read.option("sampleSizeForInferring", "10000").csv("path")就会把采样行数提升到10000行,推导准确率更高,但对应的扫描开销也会上升。
3. 类型判定的具体规则
Spark对每一列的采样值,按照「从窄类型到宽类型」的优先级做兼容校验,最终选择能兼容所有采样值的最窄类型作为该列的最终类型,判定优先级从高到低依次为:
- 空值跳过:如果采样行该列值为空,不参与本次类型判定,不影响最终类型结果
- 布尔类型(
BooleanType):校验值是否可解析为布尔值(大小写不敏感的true/false) - 整数类型(
IntegerType):校验值是否可解析为32位整数 - 长整数类型(
LongType):校验值是否可解析为64位整数 - 双精度浮点数(
DoubleType):校验值是否可解析为双精度浮点值 - 十进制类型(
DecimalType):校验值是否符合十进制数格式,根据数值精度匹配对应精度的Decimal类型 - 时间戳类型(
TimestampType):如果读取时配置了时间戳解析格式,校验值是否可匹配格式解析为时间戳 - 日期类型(
DateType):如果读取时配置了日期解析格式,校验值是否可匹配格式解析为日期 - 字符串类型(
StringType):如果以上所有类型都无法兼容采样到的列值,最终将该列判定为字符串类型
注意:默认1000行的采样逻辑如果遇到数据分布不均的场景很容易出现类型误判,比如某列前1000行都是整数,1000行之后出现小数、字符串等非整数值,正式读取时就会抛出类型转换异常。这类场景建议要么手动提前定义Schema,要么适当调大采样行数,对准确率要求极高的场景再考虑开启全量推导。
内容的提问来源于stack exchange,提问作者Ramaraju.d
相关产品推荐
相关产品推荐

