mcpField
L
ln-651-query-efficiency-auditor

ln-651-query-efficiency-auditor

github.com/levnikolaevich数据与数据库584380 次安装2 天前更新
代码仓库

关于 ln-651-query-efficiency-auditor

专门审计数据库查询模式的 Worker,会记录问题的严重程度、位置、工作量和建议,面向代码库审计并计算查询效率合规分数,不会自动修复。

主要功能

  1. 01检测重复读取和重复解析
  2. 02检查更新、删除及插入循环
  3. 03识别过量读取和缓存范围问题
  4. 04记录严重程度与改进建议
  5. 05计算查询效率评分

适用场景

  1. 01审查 ORM 代码中的重复数据库读取
  2. 02查找批量处理数据库操作的机会
  3. 03在代码库审计中评估查询模式

MCP 相关

本 Worker 优先使用 hex-line MCP 读取本地代码和配置;分析引用链或调用路径有帮助时使用 hex-graph。MCP 不可用或不适用时,会改用内置工具并在报告中注明。

安装

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

$npx skills add https://github.com/levnikolaevich/claude-code-skills --skill ln-651-query-efficiency-auditor

安装后在 Claude Code 中输入/ln-651-query-efficiency-auditor确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
audit_output_schema.md
audit_scoring.md
audit_summary_contract.md
audit_worker_core_contract.md
mcp_integration_patterns.md
mcp_tool_preferences.md
two_layer_detection.md
references/templates/
audit_worker_report_template.md

详细介绍

**路径:**文件路径(references/、../ln-*)均相对于此技能目录。

查询效率审计员(L3 Worker)

**类型:**L3 Worker

专门审计数据库查询模式,检查冗余、低效和误用情况。

用途与范围

  • 审计查询效率(优先级:高)
  • 检查冗余获取、批量操作误用和缓存范围问题
  • 将包含严重程度、位置、工作量和建议的结构化发现写入文件
  • 计算「查询效率」类别的合规评分(X/10)

输入

**必须读取:**加载 references/audit_worker_core_contract.md 和 references/mcp_tool_preferences.md。 工具策略:你可能作为独立子 Agent 运行,此时宿主的 AGENTS.md 不在适用范围内,因此读取文件、搜索和编辑时默认优先使用 hex-line MCP。仅在 MCP 行为不明确时加载 references/mcp_integration_patterns.md。

接收包含以下内容的 contextStore:tech_stack、best_practices、db_config(数据库类型、ORM 设置)、codebase_root、output_dir。

**领域感知:**支持 domain_mode + current_domain。

当引用链或调用路径有助于查询分析时,优先使用 hex-graph。本地代码/配置读取在可用时优先使用 hex-line。如果 MCP 不可用、不受支持或尚未编入索引,则继续使用内置的 Read/Grep/Glob/Bash,并在报告中说明所用的回退方式。

工作流

检测策略:采用两层检测(候选扫描,然后上下文验证);仅在验证方法不明确时加载 references/two_layer_detection.md。

  1. 解析 contextStore 中的上下文

    • 提取 tech_stack、best_practices、db_config、output_dir
    • 按与 ln-624 相同的逻辑确定 scan_path
  2. 扫描代码库中的违规项

    • 所有 Grep/Glob 模式均使用 scan_path
    • 追踪调用链以查找冗余获取(需要读取调用方和被调用方)
  3. 收集发现,包含严重程度、位置、工作量和建议

  4. 使用惩罚算法计算评分

  5. **编写报告:**按照 references/templates/audit_worker_report_template.md 在内存中构建完整的 markdown 报告,并通过一次 Write 调用写入 {output_dir}/ln-651--global.md

  6. **返回摘要:**向协调器返回最简摘要(见输出格式)

审计规则(优先级:高)

1. 实体冗余获取

**说明:**同一实体在调用链中从数据库获取两次

检测方法:

  • 查找函数 A:它调用 repo.get(id) 或 session.get(Model, id),然后将 id(而非对象)传递给函数 B
  • 函数 B 也会针对同一实体调用 repo.get(id) 或 session.get(Model, id)
  • 常见模式:acquire_next_pending() 返回 job,但 _process_job(job_id) 又重新获取该 job

检测模式(Python/SQLAlchemy):

  • 在服务/处理程序文件中搜索 repo.*get_by_id|session\.get\(|session\.query.*filter.*id
  • 追踪调用:如果函数接收 entity_id: int/UUID,且内部执行 repo.get(entity_id),则检查调用方是否已持有实体对象
  • 检查 expire_on_commit 设置:若为 False,对象在提交后仍然有效

严重程度:

  • **高:**API 请求处理程序中存在冗余获取(会增加每个请求的延迟)
  • **中:**后台任务中存在冗余获取(影响较小)
  • **降低等级的情况:**初始化/迁移代码中的获取(只运行一次)→ 低。仅管理员可访问且流量较低的端点 → 降低一个等级

**建议:**传递实体对象而不是 ID,或者在 expire_on_commit=False 时移除第二次获取

**工作量:**S(将签名改为接收对象而不是 ID)

2. N-UPDATE/DELETE 循环

内容: 循环执行单条 UPDATE/DELETE 操作,而不是使用单个批量查询

检测:

  • 模式:for item in items: await repo.update(item.id, ...) 或 for item in items: await repo.delete(item.id)
  • 模式:for item in items: session.execute(update(Model).where(...))

检测模式:

  • 搜索 for .* in .*:,并检查其后 1-3 行内是否出现 repo\.(update|delete|reset|save|mark_)
  • 搜索 for .* in .*:,并检查其后 1-3 行内是否出现 session\.execute\(.*update\(

严重程度:

  • HIGH: 循环处理超过 10 个项目(与数据库进行 N 次单独往返)
  • MEDIUM: 循环处理不超过 10 个项目
  • 降低严重程度的情况: 引导/迁移代码中的循环(只运行一次)→ LOW。仅限管理员使用的端点 → 降低一个级别

建议: 替换为单条 UPDATE ... WHERE id IN (...) 或 session.execute(update(Model).where(Model.id.in_(ids)))

工作量: M(重写查询并测试)

3. 不必要的解析

内容: 当调用方作用域中已经有某个值时,仍从数据库重新解析该值

检测:

  • 方法接收 profile_id 并据此解析 engine,但调用方已经确定了 engine
  • 方法接收 lang_code 并查询 dialect_id,但调用方已经有 lang 和 dialect
  • 模式:函数接收 X_id,执行 get(X_id) 并提取 .field,但调用方已经有 field

严重程度:

  • MEDIUM: 每次调用都会增加一次数据库查询,尤其是在高频路径中

建议: 将方法拆分为两个变体:with_known_value(value, ...) 和 resolving_value(id, ...);或者直接传入已解析的值

工作量: S-M(重构签名并更新调用方)

4. 过度获取

内容: 只需要少量字段时,却加载完整的 ORM 模型

检测:

  • 对于列数超过 10 列的模型,使用 session.query(Model) 或 select(Model),但没有 .options(load_only(...))
  • 尤其是在返回大量行的列表/搜索端点中
  • 模式:加载完整实体,但只使用其中 2-3 个字段

严重程度:

  • MEDIUM: 列数超过 15 列的大型模型用于列表端点
  • LOW: 列数少于 10 列的小型模型,或单实体端点

建议: 对列表查询使用 load_only()、defer() 或原始查询 select(Model.col1, Model.col2)

工作量: S(在查询中添加 load_only)

5. 缺少批量操作

内容: 顺序执行 INSERT/DELETE/UPDATE,而不是使用批量操作

检测:

  • 使用 for item in items: session.add(item),而不是 session.add_all(items)
  • 使用 for item in items: session.delete(item),而不是批量删除
  • 模式:循环中每次迭代都执行单条 INSERT

严重程度:

  • MEDIUM: 循环中任何顺序执行的 add/delete(错过批量优化机会)

建议: 使用 session.add_all()、session.execute(insert(Model).values(list_of_dicts))、bulk_save_objects()

工作量: S(将循环替换为批量调用)

6. 缓存作用域错误

内容: 对于很少变化的数据使用请求级缓存(应该使用应用级缓存)

检测:

  • 服务注册为请求级(例如,通过 FastAPI Depends()),且内部有缓存(_cache 字典、_loaded 标志)
  • 每次请求都会通过开销较大的查询(JOIN、聚合)填充缓存
  • 数据 TTL 远大于请求时长(例如,engine 配置、语言列表、功能标志)

检测模式:

  • 查找包含 _cache、_loaded、_initialized 属性的类
  • 检查类是否按请求创建(通过 DI 注册作用域)
  • 比较:数据变化频率与缓存生命周期

严重程度:

  • HIGH: 开销较大的查询(JOIN、子查询)仅按请求缓存
  • MEDIUM: 简单查询按请求缓存

建议: 将缓存移至应用级服务(单例),添加基于 TTL 的失效机制,或使用可配置 TTL 的 CacheService

工作量: M(更改 DI 作用域并添加 TTL 逻辑)

评分算法

必须阅读: 加载 references/audit_scoring.md。

输出格式

必须阅读: 加载 references/templates/audit_worker_report_template.md。

按照 references/audit_summary_contract.md 编写 JSON 摘要。在托管模式下,调用方会传入 runId 和 summaryArtifactPath;在独立模式下,工作程序会按照共享契约生成自己的运行级制品路径。

将报告写入 {output_dir}/ln-651--global.md,并设置 category: "Query Efficiency",检查项包括:redundant_fetch、n_update_delete_loop、unnecessary_resolve、over_fetching、missing_bulk_ops、wrong_caching_scope。

按照 references/audit_summary_contract.md 返回摘要。

当 summaryArtifactPath 缺失时,将独立运行时摘要写入 .hex-skills/runtime-artifacts/runs/{run_id}/evaluation-worker/{worker}--{identifier}.json,并可选择在结构化输出中回显相同的摘要。

Report written: .hex-skills/runtime-artifacts/runs/{run_id}/audit-report/ln-651--global.md
Score: X.X/10 | Issues: N (C:N H:N M:N L:N)

关键规则

遵循已加载的 references/audit_worker_core_contract.md。

  • 不要自动修复: 仅报告
  • 追踪调用链: 规则 1 和规则 3 要求同时读取调用方和被调用方
  • 感知 ORM: 标记冗余提取前,检查 expire_on_commit、autoflush 和会话作用域
  • 结合上下文: 数据集较小或操作不频繁时,较简单的代码可能更合适
  • 排除测试: 不要标记测试固件或设置代码

完成定义

遵循已加载的 references/audit_worker_core_contract.md。

  • 成功解析 contextStore(包括 output_dir)
  • 确定 scan_path(领域路径或代码库根目录)
  • 完成全部 6 项检查:
    • 冗余提取、N-UPDATE 循环、不必要的解析、过度提取、批量操作、缓存作用域
  • 收集问题,并注明严重性、位置、工作量和建议
  • 使用惩罚算法计算分数
  • 将报告写入 {output_dir}/ln-651--global.md(通过单次原子 Write 调用)
  • 按照契约写入摘要

参考文件

  • 审计输出架构: references/audit_output_schema.md

版本: 1.0.0 最后更新: 2026-02-04

评论

支持 Markdown