DuckDB 分析 10GB 日志 CSV:把 pandas 30 分钟查询压到 8 秒,我只做了这三步
DuckDB 分析 10GB 日志 CSV把 pandas 30 分钟查询压到 8 秒我只做了这三步说实话我最近被一个 10GB 的 Nginx 访问日志搞得很烦。业务要做一个“最近 30 天接口访问热度”的临时分析数据导出来是 10GB 的 CSV。我用 pandas 跑了几次第一次直接 OOM第二次加了dtype和chunksize分段处理跑了 30 分钟才出结果中间还卡死两次。同事在旁边说“要不你直接写 Hive SQL 吧”问题是我就一个人本地想查个数据犯得着上集群吗后来我想起 DuckDB 这个嵌入式分析型数据库。它不需要服务器一个 Python 包就能跑还能直接读 CSV/Parquet。结果很离谱同样的查询pandas 30 分钟DuckDB 8 秒。我把过程整理成三步方便你下次也直接抄作业。问题背景为什么 pandas 在这里这么慢我的日志文件格式很常规timestamp,method,path,status,response_time,remote_ip,user_agent 2026-07-15T10:00:0008:00,GET,/api/user,200,23,1.2.3.4,Mozilla/5.0...10GB 大概 1.2 亿行。我要做的其实不复杂按path分组统计 PV按remote_ip统计 Top 20 来源 IP按status分组看 4xx/5xx 占比算response_time的 P95/P99pandas 的瓶颈主要在两点它默认会把整个 CSV 读到内存光加载就要吃 40GB 左右内存。字符串列在 pandas 里开销很大聚合时临时对象又多CPU 和内存一起爆炸。不是 pandas 不行是它定位就不是给“单节点分析 10GB 日志”设计的。DuckDB 天生 columnar、向量化、支持直接读取外部文件明显更适合这个场景。第一步CSV 转 Parquet压缩和结构一起搞定DuckDB 可以直接读 CSV但日志分析是反复查询最好先把 CSV 转成 Parquet。Parquet 是列式存储压缩率高读取时还能只读需要的列。我用了一个 Python 脚本做转换importduckdb conduckdb.connect()con.execute( COPY ( SELECT strptime(timestamp, %Y-%m-%dT%H:%M:%S%z)::timestamp AS ts, method, path, status::smallint AS status, response_time::integer AS response_time, remote_ip, user_agent FROM read_csv_auto(nginx_logs.csv) ) TO nginx_logs.parquet (FORMAT PARQUET, COMPRESSION ZSTD) )这段代码有两个关键细节用strptime把带时区的字符串转成timestamp后面按时间过滤不会出错。status和response_time显式转成 smallint/integer避免 DuckDB 把数字当成大字符串处理。转换耗时大概 1 分 40 秒10GB CSV 压成了 1.4GB 的 Parquet。不是 pandas 那种“读完再写”的过程DuckDB 是一边读 CSV 一边写 Parquet内存基本稳定在 1GB 左右。第二步用 SQL 直接查 Parquet聚合快到离谱转换完之后查询就非常爽了。DuckDB 支持read_parquet直接读取文件不需要导入表。importduckdb conduckdb.connect()# Top 20 接口 PVcon.execute( SELECT path, count(*) AS pv FROM read_parquet(nginx_logs.parquet) GROUP BY path ORDER BY pv DESC LIMIT 20 ).fetchdf()# P95/P99 响应时间con.execute( SELECT quantile_cont(response_time, 0.95) AS p95, quantile_cont(response_time, 0.99) AS p99 FROM read_parquet(nginx_logs.parquet) ).fetchdf()# Top 20 来源 IPcon.execute( SELECT remote_ip, count(*) AS cnt FROM read_parquet(nginx_logs.parquet) GROUP BY remote_ip ORDER BY cnt DESC LIMIT 20 ).fetchdf()这三个查询加起来在我这台 16GB 内存的笔记本上跑了 8.2 秒。作为对比pandas 单查询groupby那一步就跑了 12 分钟以上。第一次 OOM 之后我顺手记了下对比数据方案加载时间聚合时间峰值内存文件大小pandasread_csv groupby约 8 分钟约 22 分钟41GB10GB CSVpandaschunksize分段聚合约 5 分钟约 25 分钟12GB10GB CSVDuckDB CSV→Parquet SQL约 1 分 40 秒约 8 秒1.2GB1.4GB Parquetpandas 分段聚合虽然内存下来了但代码要写多线程合并复杂度直线上升。DuckDB 这边基本就是写 SQL省下来的时间够我喝杯咖啡。顺手加了几个时间维度的查询业务不只是看总数还想看每天 4xx/5xx 的变化趋势。用 DuckDB 也很简单con.execute( SELECT date_trunc(day, ts) AS day, status, count(*) AS cnt FROM read_parquet(nginx_logs.parquet) WHERE status 400 GROUP BY day, status ORDER BY day DESC, cnt DESC ).fetchdf()date_trunc这种时间函数不需要额外导入 datetime直接写 SQL 就行。再搭配quantile_cont算分位list/unnest展开数组基本常见的日志分析需求都能覆盖。我还顺手写了一个环比查询把最近 7 天和上一周的接口 PV 做对比找出涨幅超过 30% 的接口。DuckDB 支持 CTESQL 结构和在 PostgreSQL 里写的几乎一样迁移成本很低。临时查一次可以但如果每天都想跑一遍最好封装起来。我把上面这些固定成了analyze_logs.pyimportduckdbimportsys LOG_PATHsys.argv[1]iflen(sys.argv)1elsenginx_logs.parquetconduckdb.connect()# 限制最大内存防止小机器被拖死con.execute(SET memory_limit 4GB)con.execute(SET threads 4)print( 接口 PV Top 20 )print(con.execute(f SELECT path, count(*) AS pv FROM read_parquet({LOG_PATH}) GROUP BY path ORDER BY pv DESC LIMIT 20 ).fetchdf().to_string(indexFalse))print(\n 状态码分布 )print(con.execute(f SELECT status, count(*) AS cnt, round(count(*) * 100.0 / sum(count(*)) over (), 2) AS pct FROM read_parquet({LOG_PATH}) GROUP BY status ORDER BY status ).fetchdf().to_string(indexFalse))print(\n 响应时间分位 )print(con.execute(f SELECT round(quantile_cont(response_time, 0.50), 2) AS p50, round(quantile_cont(response_time, 0.95), 2) AS p95, round(quantile_cont(response_time, 0.99), 2) AS p99 FROM read_parquet({LOG_PATH}) ).fetchdf().to_string(indexFalse))加memory_limit和threads是为了让它在笔记本上也能稳一点。如果你的机器更强可以把线程数调大。它不会像 pandas 那样冷不丁把内存吃光然后被系统 OOM killer 干掉。踩坑记录时区字符串解析容易出错我原始日志的时区格式是08:00strptime的格式串要写%Y-%m-%dT%H:%M:%S%z。如果直接read_csv_auto后按时间过滤时区会识别成字符串结果全错。CSV 里有脏数据要处理有些行的response_time是-或者空值DuckDB 默认会报错。可以在read_csv_auto里加nullstr[, -]和columns{...}或者用try_cast容错。Parquet 文件路径含通配符如果是按天拆分的日志比如logs/2026-07-*.parquet可以直接用read_parquet(logs/*.parquet)DuckDB 会自动并行读多个文件。DuckDB 版本差异0.10 之前的read_csv_auto对类型推断比较激进建议升级。我用的是 1.0.0稳定很多。不是银弹这些情况我还是选 ClickHouse 或 pandasDuckDB 虽然香但不是所有场景都合适数据超过 100GB 或者需要持续实时写入这种规模 DuckDB 单节点会比较吃力ClickHouse、Doris、Snowflake 这类真正的分布式 OLAP 更合适。要做复杂的特征工程、数据清洗流水线pandas 的 DataFrame 操作更灵活结合 DuckDB 的fetchdf()把结果拉出来再用 pandas 处理也是不错的选择。团队协作需要权限和元数据管理DuckDB 是本地文件没有用户权限、Schema 版本管理多人协作时还是得上数据库服务。我的做法是把 DuckDB 当成“本地超大数据文件分析器”导入、聚合、出数然后结果再回到 pandas 做可视化或者业务层使用。两个工具并不冲突选对场景才是关键。DuckDB 不是来替代 ClickHouse 或 Snowflake 的它真正的定位是你本地有一个几十 GB 的数据文件想快速用 SQL 查一遍不想搭服务也不想 pandas 折磨你。如果数据量超过 100GB 或者需要实时写入那还是得看真正的 OLAP 集群。但如果你像我一样经常被“临时导出的 CSV 日志”和“pandas 跑不动”之间的鸿沟卡住那 DuckDB 真的是被低估的神器。安装也简单一行命令就能搞定pipinstallduckdbDuckDB 还有官方的命令行工具duckdb如果你不想写 Python直接在 shell 里跑 SQL 也可以。我有时候临时查数就用 CLI比起一个 Python 脚本更省事。我把上面的转换脚本和分析脚本都整理好了复制过去改个路径就能跑。如果你也有类似的日志分析场景不妨试试看。有问题欢迎在评论区交流或者告诉我你用什么方案处理过大的 CSV。

相关新闻

11.Python 面向对象三大特性详解:封装、继承、多态与多继承、魔术方法及抽象类

11.Python 面向对象三大特性详解:封装、继承、多态与多继承、魔术方法及抽象类

摘要:本文系统讲解了 Python 面向对象的三大特性——封装、继承(重点涵盖多继承与 MRO)和多态,同时介绍了常用的魔术方法、魔术属性以及如何使用 abc 模块定义抽象类,帮助开发者深入理解 Python 面向对象编程的核心机制…

2026/10/15 5:54:07 阅读更多 →
浏览器自动化Agent实战:GUI操作与网页抓取完整解决方案

浏览器自动化Agent实战:GUI操作与网页抓取完整解决方案

浏览器自动化Agent实战:GUI操作与网页抓取完整解决方案 【免费下载链接】ai-agent-book 《深入理解 AI Agent:设计原理与工程实践》(李博杰 著)开源主仓库:全书正文、编译版 PDF 与按章配套代码 项目地址: https://g…

2026/10/17 16:54:39 阅读更多 →
自托管 Umami 实现 iOS 应用分析:免重量级 SDK,数据统计更精准!

自托管 Umami 实现 iOS 应用分析:免重量级 SDK,数据统计更精准!

鲁纳奥维森耶尔巴克相关信息涉及领导力、产品与技术,包含项目、文章、演讲、关于等方面。使用自托管的 Umami 进行 iOS 应用分析2026 年 7 月 14 日发布,阅读时长 7 分钟,标签有分析、iOS、应用、开源、Fly、Cloudflare。因已自托管 Umami&am…

2026/10/15 1:56:00 阅读更多 →

最新新闻

凸优化视角下的视频运动估计:十一种帧间预测算法统一框架

凸优化视角下的视频运动估计:十一种帧间预测算法统一框架

简介:这是一份面向凸优化课程大作业的完整代码包,围绕MV子视角帧间预测任务,汇聚穷尽块匹配、三步搜索法、分层块匹配三类运动估计方法,结合光流估计与单应性矩阵进行交叉组合,共实现十一种可运行方案。每种方法均配有…

2026/10/18 10:23:42 阅读更多 →
LoRA微调后如何加载与管理权重?从原理到工程实战

LoRA微调后如何加载与管理权重?从原理到工程实战

LoRA 微调这件事,圈子里聊得很多,但大部分人聊的是“怎么训”,少有人把“训完之后怎么加载、怎么管权重”讲明白。我一开始接触 LoRA 的时候也踩过不少坑——明明训练得很顺利,一加载就黑屏报错;明明两个 LoRA 单独用都…

2026/10/18 10:23:42 阅读更多 →
PPT打开密码怎么改?两种方法加避坑指南一次讲透

PPT打开密码怎么改?两种方法加避坑指南一次讲透

当拿到一份带着密码的PPT,或者自己以前设过密码却觉得不够稳妥,很多人第一反应是把文件删了重新存一份——其实不必这么麻烦。修改PPT的打开密码,本身就是几秒钟的事,只是Office藏得有点深,不少人找不着入口。这篇就把…

2026/10/18 10:23:42 阅读更多 →
开关电源Y电容全解析:从安规等级到EMI布局

开关电源Y电容全解析:从安规等级到EMI布局

设计开关电源的朋友基本都遇到过这样的场景:原理图评审时,老工程师指着初级地和次级地之间那个黄豆大小的陶瓷电容,问一句“你的Y电容容值怎么定的?”你要是只说“用了4.7nF”,接下来一定会被追问安规等级是多少、漏电…

2026/10/18 10:23:42 阅读更多 →
自建“口袋书签”:本地优先+全文索引,终结收藏找不到

自建“口袋书签”:本地优先+全文索引,终结收藏找不到

效率党最容易养成的坏习惯是什么?我的答案是“收藏强迫症”:看到一篇好文章先扔进收藏夹,攒了一堆“稍后读”却再也没打开过,等真到了要用的时候,翻遍所有工具都找不回当时存下的内容。为了根治这个问题,我…

2026/10/18 10:23:42 阅读更多 →
【实战】手把手教你搭建企业级Model Context Protocol (MCP)服务:从Spring AI到TaoToken统一通道

【实战】手把手教你搭建企业级Model Context Protocol (MCP)服务:从Spring AI到TaoToken统一通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 10:22:42 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →