mcpField
D
diagnosing-endpoint-performance

diagnosing-endpoint-performance

github.com/posthog数据与数据库76290 次安装今天更新
代码仓库

关于 diagnosing-endpoint-performance

面向调查特定缓慢、高成本或不可靠端点的诊断技能。它检查缓存、物化资格、查询历史和调用成本,给出具体建议;修改查询前需获得用户确认。

主要功能

  1. 01检查端点配置与版本
  2. 02评估缓存 TTL 和物化
  3. 03读取物化拒绝原因
  4. 04查看端点调用频率与成本
  5. 05建议缓存、物化、改写或回滚

适用场景

  1. 01诊断超时的端点
  2. 02评估高成本端点的调用模式
  3. 03判断查询是否可物化
  4. 04检查近期端点版本回归

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/posthog/skills --skill diagnosing-endpoint-performance

安装后在 Claude Code 中输入/diagnosing-endpoint-performance确认已加载。

详细介绍

诊断端点性能

此技能将分析某个具体的端点,该端点可能速度慢、成本高或不可靠,并给出明确的建议。它是 auditing-endpoints(用于发现候选端点)的深度分析对应技能。

何时使用此技能

  • “这个端点速度慢/超时了”
  • “为什么我的端点触及了成本上限?”
  • “我应该物化 X 吗?”
  • 某个端点在 auditing-endpoints 中被发现,其物化失败或调用成本高
  • 用户心中已有特定端点,并希望获得建议

如果问题涉及整个项目(“我应该清理哪些内容?”),请先使用 auditing-endpoints。

可用工具

工具用途
endpoint-get完整的端点配置:查询、当前版本、data_freshness_seconds、物化状态
endpoint-versions每个版本的历史记录(查询及物化状态);以及当前版本
endpoint-materialization-status是否符合物化条件、当前状态、上次运行时间、上次错误
endpoints-materialization-preview物化后的查询会是什么样,以及不符合条件时的拒绝原因
endpoints-last-execution-times上次调用时间(用于检查端点是否仍在使用)
execute-sql查询 query_log,查看端点级调用频率以及每次调用的时长/字节数

决策树

决定给出什么建议时,请按以下顺序逐项检查——最先适用的选项就是成本最低的修复方式。

第 1 步——是否已缓存?

获取端点并查看 data_freshness_seconds(它既设置缓存 TTL,也设置物化后的刷新频率)。如果用户的流量在此时间窗口内重复使用相同参数调用端点,那么首次调用之后的每次调用都会命中缓存,实际无需付费。

  • TTL 为默认值(24h / 86400s),且数据无需比这更新鲜 → 无需更改。
  • TTL 为下限 900s(15 min),且用户每分钟调用端点多次 → 提高 TTL。这几乎总是成本最低的首选操作。(data_freshness_seconds 是一个枚举值:900、1800、3600、21600、43200、86400、604800——最短间隔为 15 分钟。)
  • TTL 已处于下限,因为数据必须保持最新(例如,实时仪表盘)→ 缓存无济于事,转到第 2 步。

变量的取值方式在这里很重要:如果每次调用都传入不同的 user_id 或 date_from 值,缓存会有许多不同的键,提高 TTL 的帮助就较小。如果几乎每次调用都使用少数几种相同的参数组合,缓存就会很有用。

步骤 2 — 是否应该进行物化?

物化会预先计算查询,并将结果保存为定期刷新的视图。读取速度会接近即时响应,但代价是数据会因刷新间隔而过时,还需要为物化本身消耗存储和计算资源。

调用 endpoints-materialization-preview。响应会告诉你:

  • 符合条件且转换逻辑简洁 → 强烈建议物化。尤其是筛选形态可预测的端点(变量、细分维度)。
  • 不符合条件,并附有拒绝原因 → 无法物化。原因通常会提示下一步该怎么做(见步骤 3 — 重写)。
  • 符合条件,但转换逻辑复杂(范围对很多、需要复杂地重新推导聚合结果)→ 物化可以正常运行,但可能节省不了多少资源。在启用前值得先说明这一点。

启用物化后,调用方必须传入所有已物化变量——不带这些变量的调用会被拒绝(安全性:防止返回未筛选的数据)。建议启用时,同时注明哪些变量会成为必填项。

步骤 3 — 查询是否需要重写?

对于不符合物化条件的 SQL 端点,endpoints-materialization-preview 返回的拒绝原因是首要依据。该工具始终会解析成功。查看原因,并与以下要点匹配——这些要点概括了常见情况,并未涵盖服务端执行的所有检查;如果两者不一致,应以原始原因为准。手动提出重写方案:

  • 因群组细分 / 对比模式被拒绝 → 常规属性细分可以正常物化;只有群组细分会被阻止。将群组细分改为属性细分。趋势端点支持物化对比模式;其他查询类型则应移除对比模式(改为将对比时间窗口作为变量)。
  • JOIN 与变量组合使用 → 顶层 JOIN 加变量筛选会被拒绝物化,因为应用变量会改变连接后的行基数,并悄然产生错误结果(例如,LEFT JOIN 中不匹配的行会丢失变量列)。调整结构,让变量只筛选单个表——将筛选条件推入随后再进行连接的子查询 / CTE,而不是跨连接筛选。这是最常见的“看起来没问题,却无法物化”的陷阱。
  • “缺少变量” / 无界扫描 → 查询在没有筛选条件的情况下读取了过多数据。建议添加必填的时间窗口变量(例如 date_from、lookback_days)。
  • HogQL 使用 * / 非确定性函数 → 缩小所选列的范围,并尽可能用变量替换 now() / today()。
  • 没有要点匹配 → 上面的列表并不完整;实时检查会拒绝更多形式,包括 OR 中的变量、与另一个变量比较的变量、HAVING 子句中的变量、不受支持的运算符,以及无法物化的查询类型。将拒绝原因原样告知用户,并直接据此分析,而不要强行套用最接近的要点。有些原因根本没有等效的重写方式——例如 OR {variables.x} = 'all' 这种可选变量写法——应明确说明这一点,而不是改变查询的行为。

检查 endpoint-versions,确认查询近期是否有变更。回归问题往往源于某个特定提交,回退到该版本通常比重写更快。

第 4 步——实际调用的是慢版本吗?

默认只运行最新版本;只有调用方固定 ?version=N 时才会运行旧版本。因此,通常需要调整的是当前版本——除非问题出在某个固定使用的旧版本上。调用 endpoint-versions 并查看每个版本的 last_executed_at,以了解最近调用过哪些版本;如果某个物化版本的 last_executed_at 为 null 或已过时很久,那么与其调整,不如考虑取消物化或删除(请先确认——该信号只统计 API 密钥调用,可能较为稀疏)。

如需了解端点级调用频率和单次调用成本,请使用 execute-sql 查询 query_log——其中包含 query_duration_ms、read_rows 和 read_bytes,便于确认该端点调用的实际开销:

SELECT count() AS calls, max(query_start_time) AS last_called, avg(query_duration_ms) AS avg_ms
FROM query_log
WHERE name = '<endpoint_name>' AND endpoint LIKE '%/endpoints/%' AND is_personal_api_key_request

工作流

  1. 按名称识别端点。如果用户提供了 URL,请从 /api/projects/{team_id}/endpoints/{name}/run 中解析名称。
  2. 使用 endpoint-get 获取完整配置。注意:data_freshness_seconds、is_materialized、当前版本和查询类型。
  3. 使用 endpoint-materialization-status 查看物化状态(是否失败?是否符合条件?)。
  4. 使用 endpoint-versions 查看查询历史以及当前版本(除非调用方固定 ?version=N,否则调用方会使用该版本)。
  5. 如果用户提供了具体问题(“超时”“内存限制”“非常慢”),请按上述决策树逐步排查。否则,请说明这四项检查点,并询问用户符合哪一种情况。
  6. 最后给出明确建议——提高 TTL、物化、重写或回滚,并在执行前确认。

交互示例

User: "monthly_active_users is timing out for some callers"

Agent steps:
- endpoint-get monthly_active_users → HogQL endpoint, data_freshness_seconds=900,
  is_materialized=false, current version v4
- endpoint-materialization-status monthly_active_users → not materialised; eligible: true
- endpoint-versions monthly_active_users
  → v4 is current; v1–v3 are prior query revisions (callers hit v4 unless pinned)
- endpoints-materialization-preview → eligible, clean transform with one range pair

- "Three things stand out:
   1. Cache TTL is 900 seconds (the 15-min floor), but the data is
      aggregating a month — that aggressive a refresh probably isn't
      necessary. Bumping to 1 hour (3600s) would dramatically reduce
      ClickHouse load.
   2. It's eligible for materialisation with a clean transform. If
      callers can tolerate 5-15 minute staleness, materialisation
      would make reads near-instant.
   3. v4 is the current version, so callers hit it by default — the
      tuning target is clear.

   Quickest win: bump TTL to 3600s. Bigger win: materialise.

   Which trade-off matches your needs? If you need real-time freshness,
   neither helps and we'd need to rewrite the query — likely narrowing
   the aggregation window."

重要说明

  • 缓存几乎总是首选解决方案。 它无需成本、可立即撤销,也不会改变数据语义。如果提高 TTL 就能解决问题,请不要急着选择物化。
  • 物化存在隐性成本。 包括物化视图的存储、刷新计算,以及调用方必须传入所有变量这一要求。
  • 不要擅自重写查询。 修改查询会创建新版本,并可能导致调用方无法正常工作!!!请先说明建议的修改并获得同意,再执行。
  • 有三种使用情况信号。 endpoint-get 的 last_executed_at 表示端点级的最近调用时间;endpoint-versions 提供各版本自己的 last_executed_at;query_log(通过 execute-sql 查询)提供端点级调用频率和单次调用成本。这些信号都只统计个人 API 密钥调用,而且各版本的最近调用记录可能较为稀疏——在认定某个版本已停用之前,请先向用户确认。
  • “合适的”解决方案取决于 SLA,而非查询本身。 在建议物化之前,务必询问用户可接受的数据陈旧程度。对于实时仪表板,即使成本很低,存在 15 分钟延迟的物化视图也不合适。
  • 告知 PostHog 缺少什么。 如果诊断遇到产品限制(资格规则、TTL 枚举值、必需变量),请通过 agent-feedback 提醒团队。

评论

支持 Markdown