本文最初发布于 PostHog 官方博客。
在利用代理成功优化查询性能后,PostHog 团队尝试了更具挑战性的任务:使用多个并行运行的 Claude Code 会话,重写了其 SQL 解析器。最终成果包括 1.6 万行手写解析器代码、5000 行工具代码及数千行测试代码,实现了约 70 倍的性能提升(生产环境高达 454 倍)。
新解析器在所有实际应用场景中与旧版本完全等效,仅在极少数极端边缘案例中存在差异。以下是该项目的实现过程与技术洞察。
PostHog 为何需要自研 SQL 解析器?
PostHog 允许用户直接使用 SQL 访问数据,并将其转译为原生 ClickHouse SQL,主要基于以下考量:
- 提供与数据库物理布局无关的逻辑数据视图;
- 确保底层数据库变更不影响现有查询;
- 便于实施性能优化与访问控制策略。
PostHog 的核心功能(如产品分析、会话回放等)均依赖此转译流程。在转译前,需先将 SQL 解析为抽象语法树(AST)。作为处理不受信任输入的第一道关卡,解析器的安全性与准确性至关重要,下游的访问控制与优化均基于其生成的 AST 进行。
从 ANTLR 生成到手写优化的演进
早期,团队采用 ANTLR 生成解析器。虽然 ANTLR 能通过声明式语法文件自动生成代码且基于 C++ 运行,但其通用解释器机制存在性能瓶颈:
- 需将语法规则编译为 ATN(带栈的非确定性有限自动机),运行时通过图遍历解释执行,增加了抽象层开销;
- 支持任意动态前瞻,需在多路径间同步模拟直至确定唯一解,速度无法媲美手写递归下降解析器。
在 AI 编码辅助下,手写并维护高性能解析器成为可能。团队尝试了两种策略:一是侧重性能的递归下降方案(含 Pratt 表达式循环);二是模仿 ANTLR 行为但显式实现状态转换的方案。最终两者效果相当,团队确立了以现有 C++ 解析器为“预言机(Oracle)”的测试驱动开发模式,确保新解析器在实际查询中与之完全一致。
多维度的分歧点生成与测试策略
为确保新解析器的准确性,团队构建了多层次的测试体系:
基于属性的模糊测试(PBT)
利用 Hypothesis 库进行基于属性的测试,定义“新解析器输出应与 Oracle 一致”的属性。团队开发了基于 ANTLR 语法文件自动生成 SQL 的工具,并通过交换 Token、添加括号等方式增加输入变异,主动寻找导致不一致的 SQL 语句。
针对性的提示工程
针对 AI 修复方案脆弱的问题,优化了提示策略:在修复特定分歧点前,强制将语法文件及相关 C++ 源码加载至上下文窗口,确保 AI 充分理解参考逻辑,避免“遗忘”。
自动化迭代闭环
建立了高效的自动化循环:后台持续运行 PBT 及从生产日志提取的真实查询,将失败用例写入文件;AI 代理随时调取这些用例进行“深度思考”与修复;生成的精简测试用例自动加入回归套件。此外,引入基于代码覆盖率的反馈机制,针对性生成未覆盖语法结构的测试用例,发现深层边界问题。
最终迭代流程如下:
- 多源生成失败测试(PBT、真实语料、边缘情况推演);
- 精简用例并扩充回归测试集;
- 结合语法与源码分析,制定通用修复方案;
- 实施修复并生成总结;
- 全量回归验证并自动循环。
得益于新解析器的高性能,团队在生产环境启用“影子模式”,在数百万次真实解析中未发现偏差,迅速完成了流量切换。
性能飞跃与技术展望
新解析器在保持输出(AST 及源码位置)与 C++ ANTLR 版本完全一致的前提下,性能表现卓越:
新解析器基准测试结果
在生产环境中,新解析器平均速度提升达 454 倍。该解析器由 Claude Opus 4.7 生成,采用 Rust 语言编写,是一款以预测性递归下降为主体、搭载 Pratt 表达式核心并具备 LL(2) 前瞻能力的手写解析器。
这一案例预示着新的开发范式:解析器生成器可作为“预言机”提供正确性基准,而大语言模型结合模糊测试与手工微调,能够构建出性能更优的专用解析器。这不仅大幅缩短了开发周期,也为编译器前端优化提供了新思路。
原文链接:
https://posthog.com/blog/sql-parser
声明:本文由 InfoQ 翻译,未经许可禁止转载。

