mcpField
Q
querying-local-postgres

querying-local-postgres

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

关于 querying-local-postgres

面向 PostHog 开发者的本地 PostgreSQL 只读查询指南,涵盖 SQL 查询、调试和执行计划分析,并要求所有连接强制只读。

主要功能

  1. 01仅允许只读 SQL 操作
  2. 02给出本地 PostgreSQL 连接方式
  3. 03支持 EXPLAIN 查询计划分析
  4. 04提供 PostHog 表与数据库提示
  5. 05说明查询结果的调试场景

适用场景

  1. 01检查团队、项目或功能标志记录
  2. 02排查迁移、约束或重复键问题
  3. 03分析 Django 查询的执行计划

安装

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

$npx skills add https://github.com/posthog/posthog --skill querying-local-postgres

安装后在 Claude Code 中输入/querying-local-postgres确认已加载。

详细介绍

查询本地 Postgres(只读)— PostHog 仓库

用户查询:$ARGUMENTS

范围: 本仓库使用 PostgreSQL 存储应用元数据(团队、项目、标志、Django 模型等)。分析事件数据 存储在 ClickHouse 中,而非 Postgres——对于 events 类问题,除非用户明确要求使用 Postgres,否则请使用 HogQL / ClickHouse 工具。

何时使用

  • 用户要求查询数据库、检查表,或针对 Postgres 运行 SQL
  • 调试:行级检查(例如为什么某个团队/项目/标志行看起来不对)、迁移、约束、重复键
  • 性能:对 Django 或应用表执行只读 SELECT 的 EXPLAIN / EXPLAIN (ANALYZE, …)

说明

  1. 严格禁止变更——请参阅下方的“严格禁止变更”。如果用户要求任何写入或变更,请拒绝并说明此技能为只读。
  2. 将用户的问题转换为一条或多条只读 SQL 语句。
  3. 在运行前,在代码块中展示 SQL。
  4. 使用下方的命令模式运行(始终带有 PGOPTIONS='-c default_transaction_read_only=on',以强制只读连接)。
  5. 展示结果并给出简要解读(尤其是在用于调试或计划审查时)。

严格禁止变更

不要运行、建议或生成以下任何内容。 请拒绝并说明此技能为只读。

  • DML:INSERT、UPDATE、DELETE、MERGE、TRUNCATE
  • DDL:CREATE、DROP、ALTER、RENAME
  • 其他写入:COPY ... TO program、CALL(如果会变更)、GRANT/REVOKE
  • 对只读 SELECT 以外的任何内容执行 EXPLAIN ANALYZE(包括 WITH … SELECT)。不要将 DML 包装在 EXPLAIN ANALYZE 中——那会执行写入。下方的只读连接会拒绝写入,但 Agent 不得尝试此模式。
  • 任何修改数据、模式或角色的语句

允许:

  • SELECT(包括 WITH … SELECT)
  • EXPLAIN … SELECT(仅估算计划;不执行)
  • EXPLAIN (ANALYZE, …) SELECT——会执行一次 SELECT;仅用于性能分析。必须在下方的只读连接上运行。
  • SHOW、从目录视图(pg_stat_*、information_schema 等)执行 SELECT,前提是只读

如果用户请求写入操作,请说:“此技能为只读。我无法运行 INSERT/UPDATE/DELETE 或其他变更。请使用数据库客户端或迁移工具进行写入。”

EXPLAIN 和 EXPLAIN ANALYZE(性能)

目标使用什么
计划形态、估算成本、不执行EXPLAIN (FORMAT TEXT, COSTS) 或添加 VERBOSE
实际耗时、行数、缓冲区命中对 SELECT 执行 EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
缓冲区 + WAL 统计BUFFERS 需要 ANALYZE;WAL 需要 ANALYZE(PostgreSQL 13+)

安全模式: 被分析的语句必须仅是 SELECT(或 WITH … SELECT),并在只读连接上运行(见下方“用法”)。示例:

PGOPTIONS='-c default_transaction_read_only=on' psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -c "
EXPLAIN (ANALYZE, BUFFERS, VERBOSE, FORMAT TEXT)
SELECT … LIMIT 100;"

可选标志(在有用时):SETTINGS(显示非默认 GUC)、WAL(与 ANALYZE 一起使用)、TIMING(在较新版本中,ANALYZE 默认开启)。

注意事项:

  • EXPLAIN ANALYZE 会运行查询——在大扫描上可能很慢或负载很重;在探索时,优先使用有界 SELECT(例如符合生产形态的真实 WHERE、LIMIT)。
  • 生产 / 共享数据库——分析热查询或宽查询可能增加负载;当用户在意影响时,优先使用预发布环境、副本或非高峰时段。
  • 不带 ANALYZE 的 EXPLAIN——不会执行内部语句(某些特殊情况除外);仍然只能包装只读 SQL。

PostHog:连接和 DATABASE_URL

本地 Postgres(宿主机)——本技能的默认配置

日常本地查询请使用这个硬编码 URL(对应典型的 Docker Compose + 本地主机端口 5432,SSL 关闭):

设置值
Hostlocalhost
Port5432
Userposthog
Passwordposthog
Databaseposthog
SSLoff
# Prefer this unless the user says their local password/db differs
LOCAL_POSTGRES_URL='postgres://posthog:posthog@localhost:5432/posthog'

等价写法:postgresql://posthog:posthog@localhost:5432/posthog

同一服务器上的其他本地数据库:只需替换路径,例如 ...5432/posthog_persons。


配置的权威来源(应用): posthog/settings/data_stores.py(Django DATABASES、可选副本 POSTHOG_POSTGRES_READ_HOST、直连 POSTHOG_POSTGRES_DIRECT_HOST、PERSONS_DB_WRITER_URL,以及来自 products/db_routing.yaml 的产品数据库路由)。

当不使用硬编码 URL 时: 从宿主机使用相同凭据连接的做法记录在 Developing locally(fe_sendauth 排障)。确保容器正在运行。

DEBUG 开启时的默认环境变量: Django 会根据 PGHOST(默认 db)、PGUSER / PGPASSWORD、PGPORT、PGDATABASE 构建默认的 DATABASE_URL——与容器内主机名相匹配。从宿主机连接时,请使用 localhost 以及相同的用户名/密码/数据库名,除非你的 shell 已经导出了 DATABASE_URL。

多个 PostgreSQL 数据库(本地 compose 中为同一服务器;逻辑上相互独立的数据库):

  • 主应用数据库:通常为 posthog
  • Persons 数据库:posthog_persons(PERSONS_DB_WRITER_URL / PERSONS_DB_READER_URL)
  • 产品隔离数据库:按 products/db_routing.yaml 为 posthog_<name>(由 docker/postgres-init-scripts/create-product-dbs.sh 创建)
  • 其他初始化脚本可能会创建额外的数据库(例如 cyclotron)——如有需要,请查看 docker/postgres-init-scripts/

通过修改 DATABASE_URL 中的路径让 psql 指向正确的数据库(例如 .../posthog_persons)。

Rust / sqlx: 某些服务在 posthog/rust 下工作时使用 rust/.env 中的 DATABASE_URL——参见 rust/README.md。

用法(命令模式)

始终通过 PGOPTIONS='-c default_transaction_read_only=on' 强制连接为只读,这样即使生成的 SQL 有误,Postgres 也会拒绝写入。

为什么用 PGOPTIONS,而不是 SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY? 包含多条语句的 psql -c "..." 字符串会作为单个隐式事务运行。 SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY 只设置_后续_事务的默认值——正在进行中的那个事务仍然保持 它在 BEGIN 时被赋予的读写模式,因此同一个 -c 中的写入操作不会被拒绝。 PGOPTIONS='-c default_transaction_read_only=on' 在连接启动时设置 GUC,因此每个事务(包括隐式的 -c 事务)都会以 只读方式开始。内联等价写法是在 -c 字符串中作为第一条语句执行 SET TRANSACTION READ ONLY;(它影响当前事务,不同于 SET SESSION CHARACTERISTICS)。

从 PostHog 仓库根目录运行,以便相对环境变量路径能够正确解析。

默认——本地硬编码 URL(posthog / posthog @ localhost:5432 / 数据库 posthog):

PGOPTIONS='-c default_transaction_read_only=on' psql "postgres://posthog:posthog@localhost:5432/posthog" -v ON_ERROR_STOP=1 -c "SELECT 1;"

方案 A——DATABASE_URL 已在 shell 中(例如执行 flox activate 或手动 export 之后):

PGOPTIONS='-c default_transaction_read_only=on' psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -c "SELECT 1;"

方案 B——从仓库根目录下被 gitignore 的环境变量文件加载(如果那里设置了 DATABASE_URL):

npx dotenv -e .env -- bash -c "PGOPTIONS='-c default_transaction_read_only=on' psql \"\$DATABASE_URL\" -c 'SELECT ...'"
  • 在 shell 内的 SQL 中照常使用单引号表示字符串字面量;在 -c 中嵌套引号时要小心转义。
  • 除非用户另有指定,否则默认 LIMIT 100。
  • 对于宽行请使用 -x:psql ... -x -c "..."。

Schema 参考(PostHog)

  • Django 模型 → 表: 参见 posthog/models/(以及 products/ 下的产品包)。表名通常以 posthog_ 为前缀并使用蛇形命名(例如 posthog_team、posthog_user)。可在 psql 中用 \dt posthog_* 确认,或检查模型的 Meta.db_table(如果非标准)。
  • 迁移: posthog/migrations/(以及产品迁移路径)随时间定义了权威的 DDL。
  • Person 表名: 可通过 PERSON_TABLE_NAME 配置(参见 data_stores.py);默认为 posthog_person。

使用查询运行器进行调试(PostHog 风格)

  • 确认某个 team、project、user 或 feature-flag 关联存在对应行;在适用的情况下检查软删除 / deleted 字段。
  • 将计数和 join 与应用的假设进行对比(例如 membership、project access)。
  • 仅当用户连接到正确的主机时,才验证副本与主库读取差异(副本:POSTHOG_POSTGRES_READ_HOST)。
  • 对以 SQL 复制的慢 Django 查询的 SELECT 使用 EXPLAIN ANALYZE —— 注意会加载生产规模的数据。

交叉引用

  • 本地设置和 DB 注意事项:docs/published/handbook/engineering/developing-locally.md
  • 仓库 CLI:hogli(参见 .agents/skills/hogli/SKILL.md)

评论

支持 Markdown