PostHog ClickHouse 查询基准测试套件实战指南:用 ASV 持续追踪查询性能回归

发布时间:2026/9/14 14:28:10
PostHog ClickHouse 查询基准测试套件实战指南:用 ASV 持续追踪查询性能回归 PostHog ClickHouse 查询基准测试套件实战指南用 ASV 持续追踪查询性能回归【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog本文是一份面向 PostHog 后端开发者的 ClickHouse 查询基准测试Benchmark实战指南。文章以 ee/benchmarks/README.md 为核心骨架结合 benchmarks.py、helpers.py、asv.conf.json 与 measure.sh 等仓库源码系统讲解基准测试套件的架构、本地运行方法、PR 性能回归检测流程、新用例编写规范以及历史结果回填技巧。读完本文你将掌握如何在本地复现 PostHog 官方基准测试、读懂各项 ClickHouse 指标耗时、读取行数、内存占用的含义并为自己的查询优化 PR 添加可追踪的性能证据。基准测试套件定位为什么 PostHog 需要一套 ClickHouse 查询基准PostHog 的产品分析、会话回放、用户行为洞察等核心能力几乎都建立在 ClickHouse 之上的大量复杂查询之上。随着数据量增长与查询逻辑演进一次不经意的 SQL 改动或物化列策略调整都可能在线上引发显著的查询性能回退。ee/benchmarks/README.md 明确指出ee/benchmarks是PostHog ClickHouse 查询的基准测试套件benchmark suite其目标是在时间轴上持续追踪 ClickHouse 查询的性能改进tracks performance improvements to clickhouse queries over time。这意味着它不是一次性压测工具而是与 CI、PR 流程深度绑定的长期性能治理基础设施。为了获得跨时间的稳定可比较结果套件坚持两个关键设计决策基于 airspeed velocityasv驱动asv 是专门面向 Python 项目的基准测试框架负责环境构建、多次采样、结果归档与回归检测使用预填充数据的稳定 ClickHouse 节点基准测试始终跑在一个数据形态固定的 ClickHouse 节点上避免因线上数据增长导致结果失真从而保证不同提交之间的性能差异真实反映代码变化。历史基准测试结果由独立的PostHog/benchmark-results仓库承载套件本身只负责“生产”结果不负责长期保存。套件文件布局五个文件组成的性能观测体系在继续之前先整体了解ee/benchmarks目录的结构文件职责README.md使用文档安装、运行、回填、FAQasv.conf.jsonASV 框架配置文件定义项目路径、构建命令、结果目录等benchmarks.py基准用例集合定义被测查询与测试环境准备逻辑helpers.py核心支撑库Django/ClickHouse 环境初始化、benchmark_clickhouse装饰器、查询统计采集measure.sh独立于 ASV 的单查询测量脚本支持火焰图与 EXPLAIN其中benchmarks.py与helpers.py是套件的主体前者描述“测什么”后者解决“怎么稳定地测”。安装与本地运行从零跑起一套基准环境准备基准测试由 asv 驱动而 asv 依赖 virtualenv或 Anaconda 发行版来隔离基准运行环境。按 README 的说明安装只需pip install asv virtualenv需要特别说明的是PostHog 的基准用例直接运行在 Django 应用上下文中见下文helpers.py因此本地运行前还需要保证项目本身的 Python 依赖可用并且能够连上目标 ClickHouse 节点。一键本地运行README 给出了标准的本地运行流程。核心是两步先声明机器环境再执行基准# 1) 设置机器环境machine 标识用于区分不同运行环境的结果 asv machine --machine ci-benchmarks --config ee/benchmarks/asv.conf.json # 2) 运行全部基准X 替换为实际凭据 CLICKHOUSE_HOSTX CLICKHOUSE_USERX CLICKHOUSE_PASSWORDX CLICKHOUSE_DATABASEposthog asv run --config ee/benchmarks/asv.conf.json这里的环境变量直接决定了基准用例执行时连接的 ClickHouse 实例。从 helpers.py 可以看到套件运行时还强制注入了两个环境变量os.environ[POSTHOG_DB_NAME] posthog_test os.environ[DJANGO_SETTINGS_MODULE] posthog.settings也就是说无论外部传入的CLICKHOUSE_DATABASE是什么Django 侧的POSTHOG_DB_NAME恒为posthog_test这是 PostHog 测试环境与生产环境隔离的一部分。随后脚本把仓库根目录加入sys.path并调用django.setup()确保基准用例可以像正常后端代码一样使用 ORM、模型与 ClickHouse 客户端。快速迭代单个用例整套基准耗时较长日常开发中最常用的是 README 提供的“快速单测”模式asv run --config ee/benchmarks/asv.conf.json --bench track_lifecycle --quick--bench track_lifecycle是一个正则表达式匹配任何名称包含track_lifecycle的用例--quick则只让每个用例运行一次用于快速验证逻辑正确性而非采集稳定数据。关于asv run的更多参数如--steps、--date-period、--record-samplesREADME 建议查阅 asv 官方文档。基准用例剖析QuerySuite 到底在测什么benchmarks.py 是套件的用例主体其核心是一个名为QuerySuite的类。先看它的类级配置class QuerySuite: timeout 3000.0 # Timeout for the whole suite version v001 # Version. Incrementing this will invalidate previous resultstimeout 3000.0整个套件的超时上限秒避免单个提交的异常查询拖垮整轮基准version v001套件版本号。这是一个容易被忽略却非常重要的设计——一旦基准用例本身发生结构性变化例如新增了被测查询、改变了数据准备逻辑旧版本的结果与新版本不可直接比较此时应递增版本号使历史结果失效防止回归检测出现误判。当前QuerySuite定义了 5 个基准用例全部通过benchmark_clickhouse装饰器标记为被测目标用例名被测功能特别说明track_earliest_timestamp查询团队最早事件时间戳对应 timestamp_utils.py 中的get_earliest_timestamp_unfiltered是许多查询的时间范围默认值来源track_event_property_values事件属性取值查询$browser在no_materialized_columns()上下文内执行模拟无物化列场景track_event_property_values_materialized同上但允许使用物化列与上一用例成对用于量化物化列收益track_person_property_values用户属性取值查询$browser同样在无物化列上下文内执行track_person_property_values_materialized同上但允许使用物化列与上一用例成对四个属性取值用例实际复用同一个执行入口_run_event_property_values/_run_person_property_values它们都通过PropertyValuesQueryRunner运行一个标准的PropertyValuesQueryproperty_type区分 EVENT 与 PERSON并以ExecutionMode.CALCULATE_BLOCKING_ALWAYS模式强制同步阻塞执行——确保查询完整跑完指标采集落在真实执行上而不是被缓存或异步机制“糊弄”过去。setup基准数据准备的关键QuerySuite.setup()是每个提交运行前都会执行的准备逻辑其作用有三物化列准备按照模块级常量MATERIALIZED_PROPERTIES的定义为events表物化$current_url、$event_type、$host为person表物化$browser、email并通过backfill_materialized_columns(..., backfill_periodtimedelta(days1_000))回填过去 1000 天的历史数据。materialize与backfill_materialized_columns均来自 ee/clickhouse/materialized_columns/analyze.py与生产环境的物化列管理共用同一套实现保证基准环境与生产语义一致。团队数据准备由于基准服务器上的数据约定ID2setup 会优先查找Team id2不存在则创建一个名为 The Bakery 的团队并指定id2确保后续查询总是作用于同一份团队数据。人群Cohort准备查找或创建名为 benchmarking cohort 的人群其筛选条件为person.email包含.com创建后立即调用cohort.calculate_people_ch(pending_version0)计算人群成员供未来人群相关基准用例使用。这套 setup 逻辑保证了无论跑在哪个提交上基准数据的“形状”都保持一致这正是 README 强调的“稳定结果”的落地实现。运行原理benchmark_clickhouse装饰器如何采集指标性能基准最怕三件事结果抖动、采样不足、指标口径不一致。helpers.py 通过一个装饰器和一个查询统计函数解决了这些问题。单次执行的指标采集def run_query(fn, *args): uuid str(UUIDT()) tag_queries(kindbenchmark, idf{uuid}::${fn.__name__}) try: fn(*args) return get_clickhouse_query_stats(uuid) finally: reset_query_tags()执行前先用tag_queries给当前线程的后续查询打上benchmark:{uuid}::${函数名}的标签执行后get_clickhouse_query_stats通过SYSTEM FLUSH LOGS强制落盘查询日志再从system.query_log中按标签匹配出该次执行产生的所有查询SELECT query_duration_ms, read_rows, read_bytes, memory_usage FROM system.query_log WHERE query NOT LIKE %%query_log%% AND query LIKE %(matcher)s AND type QueryFinish最终聚合为四个指标query_count查询次数、ch_query_timeClickHouse 总耗时毫秒、read_rows读取行数、read_bytes读取字节数、memory_usage内存占用。读取行数与内存占用是比单纯耗时更稳健的性能信号——它们不受机器负载抖动影响能更真实地反映查询的“计算量”。装饰器的采样策略def benchmark_clickhouse(fn): wraps(fn) def inner(*args): samples [run_query(fn, *args)[ch_query_time] for _ in range(4)] return {samples: samples, number: len(samples)} return inner每个用例默认连续执行4 次采样并以 ASV 标准的{samples: [...], number: 4}结构返回——这正好对应 README 中--quick模式“只运行一次”的行为差异快速模式下number为 1。4 次采样的均值与分布由 asv 负责统计用于计算置信区间与回归判定。no_materialized_columns量化物化列收益的开关contextmanager def no_materialized_columns(): Allows running a function without any materialized columns being used in query cast(Any, get_enabled_materialized_columns)._cache { (events,): (now(), {}), (person,): (now(), {}), } yield cast(Any, get_enabled_materialized_columns)._cache {}PostHog 的查询编译器通过get_enabled_materialized_columns判断属性是否可走物化列。该上下文管理器临时把此函数对events、person的缓存置为空映射让编译器认为“没有可用物化列”从而在同一数据、同一查询下获得“无物化列 vs 有物化列”的对照数据。这正是 benchmarks.py 中四对..._values/..._materialized用例的意义用同一把尺子量化 PostHog 物化列特性带来的真实性能收益。在 CI 中持续运行master 每日基准与 PR 性能检测README 的 FAQ 部分描述了基准套件在团队协作流程中的实际地位master 分支每日自动运行基准测试每天对 master 分支执行一次形成持续的性能时间序列任何历史回归都能通过时间轴发现PR 标记performance触发评论如果你的分支包含显著的查询性能改动给 PR 打上performance标签CI action 会在 PR 上自动运行基准并评论基准结果把性能影响直接呈现在评审上下文中。这意味着性能治理不是“事后追责”而是嵌入到了日常代码评审流程中。若你的改动涉及查询性能例如调整了 HogQL 编译器、物化列逻辑或 ClickHouse 查询生成记得主动添加performance标签以获取基准反馈。新增基准用例两条规则README 给出的新增规范非常精简Edit thebenchmarks.pyfile as needed. Usebenchmark_clickhousedecorator to select tests to run即在 benchmarks.py 的QuerySuite类中添加新的方法用benchmark_clickhouse装饰该方法即可被 asv 自动发现并纳入基准。结合现有代码写一个新用例至少要注意两点一是方法内应真正执行到目标查询可参考现有用例通过PropertyValuesQueryRunner等 Query Runner 触发完整查询链路二是若用例依赖特定数据形态如人群、物化列需在setup()中补充对应的数据准备逻辑否则基准环境无法保证一致性。回填历史基准把性能曲线补到过去当你需要评估“过去一段时间”的查询性能走势或者新基准用例需要历史基线时README 提供了回填backfilling流程# 1) 将历史结果仓库克隆到套件目录下 # 将 benchmark-results 克隆到 ee/benchmarks/results # 2) 对过去约 4 天或任意历史区间的提交运行基准 CLICKHOUSE_HOSTX CLICKHOUSE_USERX CLICKHOUSE_PASSWORDX CLICKHOUSE_DATABASEposthog \ asv run --config ee/benchmarks/asv.conf.json --date-period 4d master~500.. # 3) 发布结果并提交到 benchmark-results 仓库 asv publishmaster~500..表示从 master 向前 500 个提交直到当前 HEAD 的全部历史提交--date-period 4d则按时间窗口选取提交。回填完成后asv publish会生成静态 HTML 报告输出目录对应 asv.conf.json 中的html_dir: results/docs将增量结果合入历史仓库。README 同时提示若对回填细节有疑问可直接以仓库中的 benchmark GitHub Action 工作流作为执行参考。measure.sh脱离 ASV 的单查询深度剖析除了 ASV 套件ee/benchmarks还提供了一个独立的测量脚本 measure.sh用于对单个 SQL 文件进行针对性分析。其定位与 ASV 互补ASV 负责长期回归追踪measure.sh 负责“当场把一条查询的性能与执行计划看透”。用法与参数./ee/benchmarks/measure.sh \ --clickhouse-server clickhouse-server \ --tunnel-server some-server \ --password PW \ --query-file some-query.sql支持的全部参数如下参数含义-h, --help打印帮助信息-q, --query-file要测量的查询文件路径-s, --clickhouse-serverClickHouse 服务器地址-t, --tunnel-server用于 SSH 隧道访问 ClickHouse 的中转服务器-u, --userClickHouse 用户默认default-p, --passwordClickHouse 用户密码--explain输出查询执行计划EXPLAIN PIPELINE graph1, header1--drop-cache执行前清空 ClickHouse mark cache切勿在生产环境使用--no-flamegraphs跳过火焰图生成执行细节脚本会为查询附加一组剖析设置后发送执行包括开启内省函数allow_introspection_functions1、实时与 CPU 剖析器采样周期40ms、内存剖析步长1MB与采样概率0.01、禁用未压缩缓存use_uncompressed_cache0并限制最大执行时间 400 秒——这些设置确保能采集到采样栈与内存火焰图所需的信号。查询执行完毕后脚本依次执行SYSTEM FLUSH LOGS从system.query_log反查该查询的query_id并输出event_time、query_duration_ms、read_rows、read_bytes、result_rows、memory_usage、涉及表与列等完整统计。若未禁用火焰图还会调用clickhouse-flamegraph工具按 query-id 生成火焰图并用浏览器打开便于直观定位热点函数。若指定了--tunnel-server脚本会先通过ssh -L建立本地端口转发8124 - clickhouse-server:8123让本机以localhost:8124访问 ClickHouse适合无法直连内网节点的场景。--drop-cache通过SYSTEM DROP MARK CACHE在每次执行前清空 mark 缓存用于测量冷缓存下的真实性能README 与脚本帮助信息都明确警告不要在生产环境使用。FAQ 速查把常用操作汇总成一张表场景操作检查我的 PR 是否影响查询性能在 PR 上添加performance标签CI 会自动运行基准并评论结果本地装好工具pip install asv virtualenv跑全部基准先asv machine --machine ci-benchmarks --config ee/benchmarks/asv.conf.json再带环境变量执行asv run --config ee/benchmarks/asv.conf.json快速迭代单个用例asv run --config ee/benchmarks/asv.conf.json --bench track_lifecycle --quick添加新用例在 benchmarks.py 中添加方法并用benchmark_clickhouse装饰回填历史结果克隆 benchmark-results 至ee/benchmarks/resultsasv run ... --date-period 4d master~500..再asv publish单条 SQL 深度剖析使用 measure.sh配合--explain与火焰图总结PostHog 的 ClickHouse 基准测试套件是一套“框架 用例 指标采集 CI 联动 独立剖析工具”的完整性能治理方案ASV 负责环境管理与长期回归检测benchmark_clickhouse装饰器基于system.query_log稳定采集耗时、读取行数与内存指标QuerySuite通过物化列对照用例量化特性收益performance标签把性能反馈嵌入 PR 评审measure.sh则为单查询提供执行计划与火焰图级剖析能力。无论是排查线上查询性能问题、评估自己的优化改动还是为 PostHog 贡献新的查询路径这套套件都提供了可复制、可对比、可追溯的实践范式。【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询