使用 Parquet 文件处理 Arrow 中的 UUID 值

Handling UUID values in Arrow with Parquet files

提问人:Chris Wood 提问时间:9/6/2021 最后编辑:Chris Wood 更新时间:9/28/2022 访问量:2359

问:

我是 Python 和 Pandas 的新手 - 请温柔一点!

我正在将 SqlAlchemy 与 pymssql 一起使用,以对 SQL Server 数据库执行 SQL 查询,然后将结果集转换为数据帧。然后,我尝试将此数据帧编写为 Parquet 文件:

  engine = sal.create_engine(connectionString)

  conn = engine.connect()
  df = pd.read_sql(query, con=conn)
  df.to_parquet(outputFile)

我在 SQL 查询中检索的数据包括一个名为 的列(即 UUID)。因此,我在上面的最后一行收到以下错误:uniqueidentifierrowguid

pyarrow.lib.ArrowInvalid: ("Could not convert UUID('92c4279f-1207-48a3-8448-4636514eb7e2') with type UUID: did not recognize Python value type when inferring an Arrow data type", 'Conversion failed for column rowguid with type object')

我有什么方法可以在上述事件链中的任何一点强制所有 UUID 为字符串?

一些额外的注意事项:

  • 这部分代码的目标是将 SQL 查询文本作为参数接收,并充当泛型 SQL 到 Parquet 函数。
  • 我意识到我可以做类似的事情,但它依赖于我知道哪些列有类型。当它成为数据帧时,一切都是 DataFrame,并且每个查询都会有所不同。df['rowguid'] = df['rowguid'].astype(str)uniqueidentifierobject
  • 我也知道我可以在 SQL 查询本身中将其转换为 a,但是,我希望做一些更“自动”的事情,这样编写查询的人就不会一直意外地遇到这个问题/不必记住始终转换数据类型。char(36)

有什么想法吗?

Python 熊猫 Pyarrow

评论

0赞 Pace 9/8/2021
您可以检查表架构并动态修改查询以插入强制转换,但这将相当复杂。您可以尝试查看第一行以查看它是否是 UUID,但一旦您点击没有行或所有 null 的查询,它就会失败。也许最简单的解决方案是用 to str 的 dtype 强制转换所有内容。我对 pymssql/SqlAlchemy 了解不够,不知道哪些其他类型可能表现为 .如果有其他对象,那么我认为您需要检查表的架构并在数据帧中强制转换匹配列。objectobject
1赞 seb 5/15/2022
我不明白为什么这么难,自定义序列化将在 pyarrow 2.0 中删除,并且文档对该做什么非常肤浅。只是指向一个无论如何都不处理这个问题的 IPC 功能。有关于如何定义 UuidType 并注册它的描述,但它没有说明如何自动将 Uuid 映射到 UuidType。文档需要改进。

答:

-1赞 kleberbaum 9/28/2022 #1

试用 DuckDB

engine = sal.create_engine(connectionString)

conn = engine.connect()
df = pd.read_sql(query, con=conn)
df.to_parquet(outputFile)

# Close the database connection
conn.close()


# Create DuckDB connection
duck_conn = duckdb.connect(':memory:')

# Write DataFrame content to a snappy compressed parquet file
COPY (SELECT * FROM df) TO 'df-snappy.parquet' (FORMAT 'parquet')

裁判:

评论

1赞 Alleo 8/22/2023
欣赏解决方法,但我觉得应该有一种不涉及安装 duckdb 的方法。