花开月下机器人 使用 DuckDB 分析 Parquet 文件

---

使用 DuckDB 分析 Parquet 文件

2026 年 9 月 20 日 | 作者:wang_yb


---

场景


朋友发来一个小餐馆的订单文件:restaurant_orders.parquet。他说是外卖平台导出的,想看看总共多少单、赚了多少钱、哪个菜卖得好、大家怎么付款。文件几百 MB,不算大,但也不想为了看几个数去折腾数据库。[citation:58.1][citation:58.47]


DuckDB 恰好是最适合这个场景的工具——不用建表,不用导入,直接 read_parquet()。 SQL 支持完整,窗口函数也有,单机跑,装完就能用。


---

一、安装 DuckDB


curl https://install.duckdb.org | sh


一条命令装好 CLI,进去就能跑 SQL。


---

二、预览数据


SELECT * FROM readparquet('/path/to/restaurantorders.parquet') LIMIT 5;


DuckDB 的优势在这里已经体现出来了:连 CREATE TABLE 都没写,直接查 Parquet 文件。 [citation:58.47]


---

三、了解数据结构


数据在眼前了,但先别急着动手。先看清每一列的类型:


DESCRIBE SELECT * FROM readparquet('/path/to/restaurantorders.parquet');


输出会告诉你每列的名称和类型:


| 列名 | 类型 | 说明 |

|:----|:----|:------|

| order_id | INTEGER | 订单号 |

| order_time | TIMESTAMP | 下单时间 |

| customer_name | VARCHAR | 客户名 |

| menu_item | VARCHAR | 菜品 |

| quantity | INTEGER | 数量 |

| price | DECIMAL | 单价 |

| payment_method | VARCHAR | 支付方式 |


先看类型,后面算钱才不会出错。[citation:58.47]


---

四、基础统计

总共多少单?


SELECT COUNT(*) AS total_orders

FROM readparquet('/path/to/restaurantorders.parquet');

总收入是多少?


这里有个小细节:收入是 单价 × 数量,不是只加单价。


SELECT SUM(price * quantity) AS total_revenue

FROM readparquet('/path/to/restaurantorders.parquet');


---

五、聚合分析

哪个菜卖得最好?


按销量排,比按销售额排更能指导备货:


SELECT menuitem, SUM(quantity) AS totalquantity

FROM readparquet('/path/to/restaurantorders.parquet')

GROUP BY menu_item

ORDER BY total_quantity DESC

LIMIT 5;

支付方式分布


了解顾客的付款习惯,对日常运营也有帮助:


SELECT paymentmethod, COUNT(*) AS ordercount

FROM readparquet('/path/to/restaurantorders.parquet')

GROUP BY payment_method

ORDER BY order_count DESC;


微信、支付宝、现金、银行卡,一眼就能看出哪种多。[citation:58.47]


---

六、窗口函数进阶


DuckDB 对 SQL 标准的支持非常完整,包括窗口函数。

累积收入


朋友看着总收入,想知道一天里收入是怎么一步步涨上去的:


SELECT order_time,

 SUM(price * quantity) OVER (ORDER BY ordertime) AS runningrevenue

FROM readparquet('/path/to/restaurantorders.parquet');


不用自连接,也不用写子查询。 直接看一天里收入怎么累计。[citation:58.47]

按金额排名


谁是大单客户?


SELECT orderid, customername,

 price * quantity AS order_value,

 RANK() OVER (ORDER BY price * quantity DESC) AS rank

FROM readparquet('/path/to/restaurantorders.parquet')

LIMIT 5;


---

七、Python 集成


如果要在 Python 脚本中使用 DuckDB 分析 Parquet 文件:


import duckdb

直接查询 Parquet 文件

result = duckdb.sql("""

 SELECT

 menu_item,

 SUM(quantity) AS total_quantity,

 SUM(price * quantity) AS revenue

 FROM 'restaurant_orders.parquet'

 GROUP BY menu_item

 ORDER BY revenue DESC

 LIMIT 10

""").df() # 转成 pandas DataFrame


print(result)

与 pandas DataFrame 互通

import pandas as pd

duckdb → pandas

df = duckdb.sql("SELECT * FROM 'orders.parquet'").df()

pandas → duckdb(零拷贝)

duckdb.sql("SELECT payment_method, COUNT(*) FROM df GROUP BY 1")


---

八、导出结果


-- 查询结果导出为 Parquet

COPY (

 SELECT menu_item, SUM(quantity) AS qty

 FROM read_parquet('/path/to/orders.parquet')

 GROUP BY menu_item

) TO 'summary.parquet' (FORMAT PARQUET);


-- 也可以导出为 CSV

COPY (

 SELECT * FROM read_parquet('/path/to/orders.parquet')

 WHERE payment_method = '微信'

) TO 'wechat_orders.csv' (FORMAT CSV, HEADER);


---

九、适用场景


这套流程最适合以下场景:[citation:58.47]


| 场景 | 说明 |

|:----|:------|

| 手头有 Parquet 文件想快速看数 | 不用建表、不用导入 |

| 不想为了几个查询上 Spark 或建数仓 | 零运维,本地跑 |

| 需要 SQL 聚合、分组、窗口函数 | DuckDB 完整支持 |

| 数据科学工作流 | 与 pandas / Polars 无缝集成 |

| CI 中验证数据管道输出 | 进程内,不需要数据库服务 |


---

十、一句话总结

DuckDB + Parquet 的组合,让你在拿到一个几百 MB 的 Parquet 文件时,不需要导入数据库、不需要启动 Spark、不需要写 Python 脚本做逐行处理——装好 DuckDB,直接 read_parquet(),然后写 SQL 就行了。 从安装到跑出第一个分析结果,大概只需要两分钟。[citation:58.47]


发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Top