关于 mcp-developer-analysis
此技能通过 MCP Developer 端点分析 Materialize 环境,指导目录发现、性能与资源检查,并生成含优化建议的结构化报告。
主要功能
- 01系统目录发现
- 02新鲜度与水合状态检查
- 03内存与 CPU 分析
- 04工作节点偏斜调查
- 05结构化发现与建议
适用场景
- 01盘点已部署的 Materialize 对象
- 02调查延迟或水合问题
- 03检查副本资源使用情况
- 04定位工作节点间的性能失衡
MCP 相关
使用 Materialize MCP Developer 端点提供的只读查询工具检查系统目录,并在工具可用时查询指定集群上的用户对象。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ materializeinc/ agent-skills --skill mcp-developer-analysis安装后在 Claude Code 中输入/mcp-developer-analysis确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
mcp-client-connect.mdREADME.mdreferences/queries.mdreport-template.md详细介绍
Materialize 开发者分析
通过 MCP Developer 端点分析 Materialize 环境,并生成一份包含健康状态、性能发现和优化建议的结构化报告。假设 Materialize 版本为 v26.24 或更高。
开发者端点提供两个只读工具:
query_system_catalog— 对系统目录表(mz_*、pg_catalog、information_schema)执行SELECT/SHOW/EXPLAIN。不接受 cluster 参数;即使传入了参数,也会被静默忽略,而非报错。当auto_route_catalog_queries开启(默认设置)时,目录查询会自动路由到目录服务集群(mz_catalog_server);路由器无法在该集群上处理的查询——尤其是所有mz_introspection关系的查询——则会在会话的默认集群上执行(如果设置了角色的cluster默认值,则使用该值;否则使用系统默认值quickstart,除非操作员已修改)。大多数目录查询都应使用此工具。query(在 Materialize v26.30 中添加)— 对角色有权访问的任何对象执行SELECT/SHOW/EXPLAIN,并在必需的cluster参数指定的集群上运行(从 v26.33 起,还可选填cluster_replica)。执行EXPLAIN ANALYZE(必须在 MV/索引所在的集群上运行)以及直接读取用户数据时,必须使用此工具。如果操作员禁用了enable_mcp_developer_query_tool,此工具可能会被隐藏。
将 MCP 客户端连接到 materialize-developer
如果用户询问如何将 MCP 客户端(Claude Code、Cursor、VS Code、Zed、Continue、Windsurf、Claude Desktop)配置、连接或设置为与 materialize-developer 服务通信——包括如何控制连接所用的用户或角色,或如何在不同身份之间切换——请参阅 mcp-client-connect.md。其中介绍了 Emulator、Materialize Cloud 和自管理部署,并提供了各客户端的代码片段、身份验证模式和验证方法。
本 SKILL.md 的其余部分介绍连接后如何分析环境。
发现表和列
不要猜测列名。 系统目录关系包含表、视图、物化视图和源,因此没有单个 SHOW TABLES 或 SHOW VIEWS 能列出所有对象;请使用 SHOW OBJECTS FROM <schema>。mz_internal 中的本体视图描述了目录;请使用这些视图来发现正确的表、列、联接路径和 ID 类型:
| 表 | 说明 |
|---|---|
mz_internal.mz_ontology_entity_types | 现有的目录实体,以及它们映射到的 mz_* 表。 |
mz_internal.mz_ontology_link_types | 实体之间的关系(外键、指标等)。 |
mz_internal.mz_ontology_properties | 每个实体的列名、类型和说明。 |
mz_internal.mz_ontology_semantic_types | 类型化的 ID 域(CatalogItemId、ReplicaId 等)。 |
示例查询:
-- Find the right table for an entity
SELECT name, relation, description
FROM mz_internal.mz_ontology_entity_types
WHERE name LIKE '%source%'
-- Find join paths between entities
SELECT name, source_entity, target_entity, properties, description
FROM mz_internal.mz_ontology_link_types
WHERE source_entity = 'source' OR target_entity = 'source'
-- Find columns for a table
SELECT column_name, semantic_type, description
FROM mz_internal.mz_ontology_properties
WHERE entity_type = 'source_status'
查询前,请使用 SHOW COLUMNS FROM <schema>.<table> 验证列名。
重要规则
服务自身的 initialize 说明中包含目录相关注意事项:例如 last_status_change_at 等列名、mz_cluster_replica_utilization 的副本到集群的 JOIN、本体视图,以及从 v26.40 起的 mz_introspection 路由和 ID 类型。大多数客户端都会转发这些说明;如果你的客户端不会,则可使用 SHOW COLUMNS 作为替代。
mz_introspection 关系需要使用 query 工具
每个 mz_introspection 关系(包括 mz_dataflow_arrangement_sizes)都限定于集群,而 query_system_catalog 无法指定集群,因此通过该工具读取时会落到会话的默认集群:如果该集群恰好有一个副本,你会得到该副本的数据,或者得到空结果,且不会报错;如果有多个副本,读取会失败并提示 log source reads must target a replica;如果没有副本,则会提示 has no replicas available to service request。请使用带 cluster 参数的 query 读取这些关系;对于有多个副本的集群,还要使用 cluster_replica(从 v26.33 起支持,不计费的副本也算),这正是第一个错误要求的操作;第二个错误则无法通过此方式解决。
v26.40 之前的服务器会在其 initialize 指令中要求不要查询
mz_dataflow_arrangement_sizes;这条规则早于 query
工具,此处说明优先于该规则。相关查询、通往目录的联接路径及注意事项,见
references/queries.md 中的 Arrangement Sizes。如果没有
query 工具,请改用下面“内存和资源消耗”部分中的关系。
工作流概览
- 连接 — 确认 MCP Developer 工具可用
- 发现 — 使用本体和目录查询,盘点所有已部署对象
- 分析 — 评估性能指标:新鲜度、水合状态、内存、利用率
- 报告 — 生成包含发现和建议的结构化 Markdown 报告
步骤 1:验证 MCP 连接
确认你可以使用 query_system_catalog 工具。运行一个快速测试:
query_system_catalog: SELECT mz_version() FROM mz_catalog.mz_databases LIMIT 1
query_system_catalog 会拒绝不引用系统目录表的 SELECT,因此单独执行 SELECT mz_version() 会失败,并提示 Query must reference at least one system catalog table,这看起来像是连接故障。
检查客户端提供的工具中是否有 query 工具。使用该工具,你还可以对命名集群上的用户对象运行 EXPLAIN ANALYZE 和查询;如果没有该工具(因为操作员禁用了它,或使用的是 v26.30 之前的版本),则对所有适用的操作使用 query_system_catalog。
如果 query_system_catalog 失败,请检查:
- MCP 服务已在客户端的 MCP 配置中注册(不同客户端使用的文件和键各不相同,详见
mcp-client-connect.md) - 环境中已启用
enable_mcp_developer功能标志 - 身份验证凭据有效
运行查询
每次调用中,两种工具都只接受一条只读语句,不支持 SET,且末尾不能有分号(可以有一个;两个语句会被拒绝)。
结果以不带列名的裸行数组形式返回,所有 AS 别名都会被丢弃,因此请按位置映射列,并让 SELECT 列表保持简短,且按你打算读取的顺序排列。数字会以字符串形式返回,布尔值会以 JSON true/false 形式返回,NULL 会以 null 形式返回;timestamp 和 timestamptz 值会以毫秒级 Unix 纪元时间戳字符串形式返回(1787687415336.000),需要可读时间时,请将它们转换为 text。如果对象不在当前会话所在的数据库中(SHOW database),请使用数据库名称限定对象名,否则语句会因 unknown schema 而失败。响应有大小上限(默认 1 MB),请求也有超时时限(默认 60 秒);两者都可由运维人员配置,超限时都会报错。使用 LIMIT 可以让目录枚举结果不超过上限;它只会减少对单个索引关系的简单读取所需的工作量,不会减少连接查询的工作量。超时会释放此次调用,但查询有时仍会继续运行,因此不要原样重试超时的语句。
query_system_catalog 通过遍历 FROM 子句中的表引用来检查允许列表,因此不含此类引用的语句完全不会经过检查:SHOW TABLES、SHOW COLUMNS、SHOW CREATE 各种形式以及对象级 EXPLAIN ANALYZE 都可以通过检查并指定用户对象(这也是后者会返回空结果的原因,见“Worker Skew”)。仅在缺少 query 时将其作为后备方案;查询用户对象时请使用 query。
过滤系统架构时,务必始终排除:mz_catalog、mz_internal、pg_catalog、information_schema 和 mz_introspection。SHOW SCHEMAS 还会列出 mz_catalog_unstable 和 mz_unsafe,其中不包含任何关系。
步骤 2:发现 — 清点环境
运行发现查询,了解已部署的内容。完整查询集请参见
references/queries.md。发现阶段包括:
环境概览
- Materialize 版本
- 集群和副本——名称、
managed、副本数量和规格。请从mz_clusters开始并 LEFT JOIN 副本,否则没有副本的集群会从清单中消失。非托管集群的size和replication_factor为 NULL;未计费的支持副本列在mz_internal.mz_internal_cluster_replicas中,与其他副本一样计数。 - 正在使用的架构
已部署对象清单
- 源:类型(Kafka、Postgres、MySQL、Webhook 等)、集群分配、状态。
mz_sources还会为每个子源和progress集合各包含一行,因此统计源数量前,请先筛选type NOT IN ('subsource', 'progress')。 - 物化视图:集群分配、索引、依赖关系
- 视图:(非物化视图)及其使用模式
- Sink:类型、目标位置、集群分配
- 索引:所属对象、集群分配
- 连接:已配置的外部系统连接
对象定义
使用 references/queries.md 获取物化视图、视图、索引和源的 SQL 定义。这对优化分析至关重要——SQL 定义会告诉你内容的计算方式:
- 连接模式和连接顺序
- 筛选谓词(或缺失的筛选谓词——缺少时间筛选是常见问题)
- 聚合策略
- 物化视图是否重复了本可共享的逻辑
步骤 3:分析 — 性能和资源指标
新鲜度(延迟分析)
查询 mz_internal.mz_materialization_lag 获取每个对象的延迟。其 local_lag
和 global_lag 列是普通的 interval,可直接比较和排序;slowest_global_input_id 则指出导致对象落后的输入。两种延迟都以输入的前沿为基准,而非墙上时钟:如果源已暂停,管道会显示零延迟,但数据可能变得任意陈旧,因此还要将 mz_frontiers.write_frontier 与 now() 比较(参见 Write Frontiers 查询)。
write_frontier 不在此关系中,而是在 mz_internal.mz_frontiers 中,类型为 mz_timestamp。将其转换为 timestamptz 可获得易读的时间,转换为 text(再转为 bigint)可获得原始数值,不能直接转换为 bigint。查询语句见 references/queries.md。
水合状态
查询 mz_internal.mz_hydration_statuses,检查所有数据流是否已水合。初次启动后仍未水合的对象可能表示资源压力或配置问题。对副本列使用 LEFT JOIN:没有可供水合的副本时,replica_id 为 NULL;内连接会隐藏这些对象。
内存和资源消耗
- 使用
mz_internal.mz_cluster_replica_utilization获取每个副本进程的内存/CPU 百分比 - 使用
mz_internal.mz_cluster_replica_metrics获取原始内存指标;每个(副本、进程)对应一行 - 使用
mz_internal.mz_index_advice确定哪些 MV/索引可以优化
Worker 偏斜(各 worker 之间的 CPU 不均衡)
使用 WITH SKEW 查找某个 worker 承担了不成比例的 CPU/内存工作的算子。
请通过 query 工具运行这些命令,而不是 query_system_catalog:
EXPLAIN ANALYZE 会在你通过 cluster 参数指定的集群上执行;对于对象级命令,该集群必须是 MV/索引所在的集群。选错集群不一定会报错:在另一个单副本集群上,或默认集群只有一个副本时通过 query_system_catalog 运行,对象级命令会返回空结果,看起来像是“没有偏斜”;有多个副本时,读取会失败并提示 log source reads must target a replica;没有副本时,则会提示 has no replicas available to service request。不使用 query,本节内容就无法实际操作。
集群级别(在要检查的集群上运行):
EXPLAIN ANALYZE CLUSTER CPU WITH SKEW
对象级别(对 MV 及其索引都运行):
EXPLAIN ANALYZE CPU WITH SKEW FOR MATERIALIZED VIEW <schema>.<mv_name>
EXPLAIN ANALYZE CPU WITH SKEW FOR INDEX <schema>.<index_name>
如果存在偏斜:确定发生偏斜的算子(通常是 TopK/window/agg/join/distinct),然后检查定义(SHOW CREATE ...),并建议具体的 SQL 更改(移除/调整提示、重构键/分区,或重写 MV)。
索引建议
查询 Materialize 内置顾问 mz_internal.mz_index_advice。它会准确给出六种建议:keep、drop unless queried directly、convert to a view、convert to a view with an index、convert to materialized view、add index。筛选部分建议会悄无声息地漏掉实际建议;各项含义见 references/queries.md。
成本分析(可选)
使用 references/queries.md 中的 Cost Analysis 查询(按副本定价)。
撰写建议时,始终量化 credits 的影响(credits 是 Cloud 的计费单位;在自管理部署中,随附规格使用 Cloud 的数值,而操作员自定义的规格使用操作员设定的数值,默认为 0,因此最多只能将其作为相对权重呈现)。
对象依赖关系
查询 mz_internal.mz_object_dependencies 以了解依赖关系图。
第 4 步:报告 — 生成分析结果
按照 references/report-template.md 生成结构化 Markdown 报告,包含执行摘要、集群拓扑、已部署对象、性能分析(新鲜度、水合状态、资源利用率、worker 偏斜、源和接收器健康状况)、成本分析、索引建议、SQL 级别分析,以及附有具体 SQL 的编号建议。
集群拓扑表取自 references/queries.md 中的 Cluster Topology 查询,以及其中 Current Compute Cost per Cluster 的 credits 列。
撰写建议
**始终包含具体的 SQL 命令。**例如:
正确:
建议: 将
my_schema.unused_mv去物化以节省内存。SHOW CREATE MATERIALIZED VIEW my_schema.unused_mv DROP MATERIALIZED VIEW my_schema.unused_mv CREATE VIEW my_schema.unused_mv AS <definition>
错误:
建议: 考虑将
my_schema.unused_mv去物化。
故障排查手册
结尾务必提供用于修复问题的具体 SQL 命令,且未经用户同意,绝不要执行这些命令:扩容或添加副本会产生费用,删除或修改对象会丢失状态。下面的所有修复方案都是 DDL,两种工具都会拒绝执行,因此应将命令交给用户。
“为什么我的物化视图已过时?”
诊断步骤:
- 首先检查 MV 所在集群是否有副本:使用
mz_clustersLEFT JOINmz_cluster_replicas(Clusters and Replicas 查询),不要看replication_factor,因为非托管集群中的该值为 NULL,且无法反映 未计费的副本。没有副本的集群不会运行任何内容,后续步骤也难以发挥作用。 - 检查
mz_internal.mz_hydration_statuses——MV 是否已完成水合,以及集群上的其他所有对象是否都已完成水合(Non-Hydrated Objects 查询,并限定在该集群内)? - 检查
mz_internal.mz_cluster_replica_status_history中是否有近期原因 为oom-killed的offline事件;这涵盖 cgroup OOM killer、堆限制器以及 lgalloc 溢出磁盘已满这几种情况(Replica Restarts 查询;模拟器不会记录原因,因此应根据offline次数判断):OOM 循环中,当前状态通常会显示online,利用率采样值也可能不高。大多数 OOM 发生在水合期间,因此当步骤 2 显示所有内容都已完成水合,且每个进程最新的历史记录行为online时,循环就结束了;水合完成后仍反复发生的终止属于稳态循环,只有调整规格或减少集群上的负载才能解决。 - 检查
mz_internal.mz_cluster_replica_utilization:memory_percent接近 100 表示 RAM 已满,进一步增长的部分会进入交换空间(如果存在),表现为水合缓慢或延迟;heap_percent(RAM 加交换空间相对于限制的占比)不断上升,而memory_percent保持不变,说明正在使用交换空间;接近 100 时,下一次峰值就会导致副本被终止。无论哪种情况:都可以扩容、迁移 MV,或减少集群承载的内容(见下方修复方案和步骤 7)。 - 检查
mz_internal.mz_source_statuses——上游数据源是否有错误? - 检查
mz_internal.mz_materialization_lag,查看 MV 的延迟(参见“新鲜度”) - 如果
query工具可用,请在 MV 所在集群上运行EXPLAIN ANALYZE MEMORY FOR MATERIALIZED VIEW <schema>.<mv>,查看每个运算符的内存使用情况,并找出开销较大的结构(大型整理结构、没有索引的连接、缺少时间过滤条件)。
常见修复方案:
如果 MV 所在集群没有副本:
ALTER CLUSTER <cluster_name> SET (REPLICATION FACTOR 1)
-- Unmanaged cluster: add a replica directly
CREATE CLUSTER REPLICA <cluster_name>.r1 (SIZE = '<size>')
如果集群过载(内存/CPU 使用率高):
-- Option A: Scale up the cluster (unmanaged: DROP and CREATE its replicas
-- at the bigger size instead)
ALTER CLUSTER <cluster_name> SET (SIZE = '<next_size_up>')
-- Option B: Move the MV to a different cluster
SHOW CREATE MATERIALIZED VIEW <schema>.<mv_name>
DROP MATERIALIZED VIEW <schema>.<mv_name>
CREATE MATERIALIZED VIEW <schema>.<mv_name> IN CLUSTER <new_cluster> AS <definition>
如果上游数据源未运行:
SELECT name, status, error, last_status_change_at
FROM mz_internal.mz_source_statuses
WHERE status != 'running'
并非所有非 running 状态都表示故障,只有 stalled 状态会带有
error;下文“我的数据源是否正常?”会列出每种状态的含义。请先解决上游数据源的问题。MV 的新鲜度取决于数据源的健康状况。
“为什么我的集群内存不足?”
诊断步骤:
- 查看
mz_internal.mz_cluster_replica_utilization中的内存百分比,以及mz_cluster_replica_status_history中的oom-killed事件(副本重启) - 查看
mz_internal.mz_index_advice,找出可以取消物化的 MV - 检查 MV 定义中是否缺少时间过滤器
- 检查是否存在冗余索引
- 如果有
query工具可用,在可疑对象所在的集群上运行EXPLAIN ANALYZE MEMORY FOR MATERIALIZED VIEW <schema>.<mv>(或FOR INDEX <name>),查看哪些运算符占用的内存最多——这是确认哪种编排方式造成问题的最直接方法。
常见修复方法:
取消不需要物化的 MV:
SELECT o.name, o.type, sc.name AS schema_name, ia.hint, ia.details
FROM mz_internal.mz_index_advice ia
JOIN mz_catalog.mz_objects o ON ia.object_id = o.id
JOIN mz_catalog.mz_schemas sc ON o.schema_id = sc.id
WHERE ia.hint = 'convert to a view'
convert to a view with an index 和 convert to materialized view 也是内存建议,但对应的修复方式不同,因此在执行此操作前,请阅读完整的建议集(references/queries.md 中的 Index Advice 查询)。
-- For each candidate:
SHOW CREATE MATERIALIZED VIEW <schema>.<mv_name>
DROP MATERIALIZED VIEW <schema>.<mv_name>
CREATE VIEW <schema>.<mv_name> AS <definition>
删除未使用的索引:
SELECT o.name, o.type, sc.name AS schema_name, ia.hint, ia.details
FROM mz_internal.mz_index_advice ia
JOIN mz_catalog.mz_objects o ON ia.object_id = o.id
JOIN mz_catalog.mz_schemas sc ON o.schema_id = sc.id
WHERE ia.hint = 'drop unless queried directly'
-- Verify with the user before dropping
DROP INDEX <schema>.<index_name>
扩容集群(非托管集群:改为 DROP 并以更大的规格 CREATE 其副本):
ALTER CLUSTER <cluster_name> SET (SIZE = '<next_size_up>')
“我的源运行正常吗?/ 我的源是否已完成快照?”
诊断步骤:
- 查看
mz_internal.mz_source_statuses中的源错误 - 查看
mz_internal.mz_source_statistics中的摄取进度 - 查看
mz_internal.mz_materialization_lag中的端到端延迟
常见修复方法:
如果源未运行:
SELECT name, status, error
FROM mz_internal.mz_source_statuses
WHERE status != 'running'
状态包括 created(尚未记录状态)、starting、running、paused、stalled 或 dropped;文档还列出了 failed,但代码不会产生此状态。只有 stalled 状态会附带 error。Webhook 和 progress 行的状态始终为 running。created 和 starting 是正常的临时状态;paused 表示源所在的集群没有副本,再怎么等待也无法解决:
-- paused: give the source's cluster a replica
ALTER CLUSTER <cluster_name> SET (REPLICATION FACTOR 1)
-- unmanaged cluster: CREATE CLUSTER REPLICA <cluster_name>.r1 (SIZE = '<size>')
-- stalled/failed on bad credentials:
ALTER SECRET <secret_name> AS '<new_value>'
如果 snapshot_committed 为 false,说明源仍在加载初始快照。对于大型源,这是正常现象——请等待加载完成;源或副本启动后的约两分钟内,即使计数器为零,它也会显示 false。如果源完全没有 mz_source_statistics 行,说明它从未运行过,因此请检查其状态以及所在集群是否有任何副本,而不是继续等待;已暂停的源会保留过时的行,因此请先查看 status。
“我的环境运行状况如何?”
按顺序运行以下检查:
mz_internal.mz_cluster_replica_statuses— 所有用户集群的副本是否都已就绪,且mz_cluster_replica_status_history中近期没有oom-killed事件?mz_internal.mz_source_statuses— 所有源是否都在运行?mz_internal.mz_sink_statuses— 所有 Sink 是否都在运行?mz_internal.mz_cluster_replica_utilization— 是否存在资源压力?
“我可以优化哪些方面来节省成本?”
- 查看
mz_internal.mz_index_advice,找出优化候选项 - 检查集群利用率——集群是否配置过度?
- 查看
mz_catalog.mz_cluster_replica_sizes中的信用点费率
备注
- 访问权限由 RBAC 管理,因此你只能看到凭据有权访问的数据。目录不受同样的限制:即使角色没有对象授权,仍可读取完整的对象清单、每个视图和 MV 的
definition,以及全部mz_index_advice。启用 RBAC 时,query和所有不会自动路由的读取操作还需要在其运行所在的集群上拥有USAGE权限(mz_catalog_server会向PUBLIC授予该权限)。是否进行 RBAC 检查取决于部署方式及其配置;运行SHOW enable_rbac_checks和SHOW enable_session_rbac_checks即可查看(任一项为on都会启用检查)。 - 新鲜度数值是某一时刻的快照。请重新运行以检查延迟是否稳定或正在增长。