polars 0.20 用 scan_parquet 读按天分区的目录,今天新增文件里 order_id 从 int64 变成 string,collect 时抛 SchemaError: data type mismatch for column order_id,单读旧文件正常,给 scan 指定 schema 后报错换到另一列。
一开始怀疑是「上游把空值写成了字符串 null」,查了一圈,方向不对。
把日志和配置对完,能解释这个现象的基本就这几处。新旧文件同名列的数据类型不同。还有一种是分区目录里混进了 _SUCCESS 空文件。
还有一种情况,列顺序变化被当成不同 schema。
动手时先逐文件打印 schema 找出差异
python -c "import polars as pl,glob;[print(f,pl.read_parquet_schema(f)) for f in glob.glob('data/*.parquet')]"
scan 时显式 cast 成统一类型
python -c "import polars as pl;print(pl.scan_parquet('data/*.parquet').with_columns(pl.col('order_id').cast(pl.Utf8)).collect().shape)"
然后用放宽模式合并多份数据
python -c "import polars as pl;print(pl.concat([pl.read_parquet(f) for f in ['a.parquet','b.parquet']],how='diagonal_relaxed').shape)"
等前面都确认过,再写入端固定 schema 并加一次校验
python writer.py --schema schema.json --validate true
这类改动我都写进变更记录,过两周再出问题时能对上号。
恢复的判定其实很直接。collect 成功且 order_id 全部为字符串,行数等于各分区之和,没有空文件导致的额外行。
补一句。scan 是惰性的,类型错误往往在 collect 或 sink 时才抛出,别在 scan 那一行找原因。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。
