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

如何在Python中对比Parquet文件与数据库Schema(含Decimal精度)

如何在Python中对比Parquet Decimal列与数据库Schema

完全可以以Decimal类型读取Parquet文件并对比精度和刻度,不用转成double(转double会丢失精度,反而影响对比)。下面是具体实现步骤:

1. 读取Parquet文件并保留Decimal原始类型

PyArrow可以直接读取Parquet中的Decimal元数据,不需要自动转成double。通过读取文件的schema就能直接获取列的精度和刻度:

import pyarrow as pa
import pyarrow.parquet as pq

# 读取Parquet文件,保留原始类型
parquet_table = pq.read_table("target_file.parquet")

# 提取所有Decimal类型列的信息
parquet_col_info = {}
for field in parquet_table.schema:
    if pa.types.is_decimal(field.type):
        parquet_col_info[field.name] = {
            "precision": field.type.precision,
            "scale": field.type.scale
        }

如果需要转成Pandas DataFrame并保留Decimal类型,可以用convert_decimals=True参数:

import pandas as pd

df = parquet_table.to_pandas(convert_decimals=True)
# 验证列类型:此时Decimal列的类型为pd.DecimalDtype
for col in df.columns:
    dtype = df[col].dtype
    if isinstance(dtype, pd.DecimalDtype):
        print(f"{col}: Decimal({dtype.precision}, {dtype.scale})")

2. 获取数据库的Schema信息

根据你使用的数据库类型,查询对应的系统表提取numeric/decimal列的精度和刻度。以下是两种常见数据库的示例:

PostgreSQL示例(用SQLAlchemy)

from sqlalchemy import create_engine, inspect

# 初始化数据库连接
engine = create_engine("postgresql://user:password@host:port/db_name")
inspector = inspect(engine)

# 提取目标表的列信息
db_col_info = {}
table_columns = inspector.get_columns("target_table")
for col in table_columns:
    if col["type"].startswith("numeric") or col["type"].startswith("decimal"):
        # 解析numeric(38,22)格式的类型字符串
        type_detail = col["type"].strip("()").split("(")[1].split(",")
        db_col_info[col["name"]] = {
            "precision": int(type_detail[0]),
            "scale": int(type_detail[1])
        }

MySQL示例(用SQLAlchemy)

MySQL的系统表直接提供了精度和刻度的字段,无需解析字符串:

table_columns = inspector.get_columns("target_table")
db_col_info = {}
for col in table_columns:
    if col["type"].startswith("decimal"):
        db_col_info[col["name"]] = {
            "precision": col["numeric_precision"],
            "scale": col["numeric_scale"]
        }

3. 对比Parquet与数据库的Schema

将两者的列信息逐一匹配,验证精度和刻度是否一致:

# 遍历Parquet的Decimal列
for col_name, pq_type in parquet_col_info.items():
    if col_name not in db_col_info:
        print(f"警告:列 {col_name} 在数据库中不存在")
        continue
    
    db_type = db_col_info[col_name]
    if pq_type["precision"] == db_type["precision"] and pq_type["scale"] == db_type["scale"]:
        print(f"列 {col_name}: 类型匹配 - Decimal({pq_type['precision']}, {pq_type['scale']})")
    else:
        print(f"错误:列 {col_name} 类型不匹配!Parquet是Decimal({pq_type['precision']}, {pq_type['scale']}),数据库是numeric({db_type['precision']}, {db_type['scale']})")

注意事项

  • 确保Parquet文件在写入时保留了Decimal元数据:如果是用其他工具写入的Parquet,可能会把Decimal转成double,这种情况下无法恢复原始精度,需要检查写入时的配置(比如PyArrow写入时要指定type=pa.decimal128(precision, scale))。
  • 多数数据库中numeric和decimal是同义词,对比时无需区分两者的名称。
  • 不要用double类型来做对比:double是浮点数,无法精确表示Decimal的所有值,会导致精度丢失,完全不适合用来验证Schema。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 01:10:28