ln-651-query-efficiency-auditor について
データベースクエリの非効率なパターンを監査し、重要度、場所、工数、推奨事項とともに所見を記録するワーカーです。コードベース監査向けで、修正は行わずクエリ効率のスコアを算出します。
主な機能
- 01重複取得と不要な再解決の検出
- 02更新・削除・挿入ループの確認
- 03過剰取得とキャッシュ範囲の問題特定
- 04重要度と推奨事項を含む所見の記録
- 05クエリ効率スコアの算出
活用シーン
- 01ORM コード内の重複したデータベース読み取りの確認
- 02データベース操作を一括化できる箇所の特定
- 03コードベース監査でのクエリパターン評価
MCP 対応
ローカルコードや設定の読み取りには 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.mdaudit_scoring.mdaudit_summary_contract.mdaudit_worker_core_contract.mdmcp_integration_patterns.mdmcp_tool_preferences.mdtwo_layer_detection.mdreferences/templates/audit_worker_report_template.md詳細
パス: ファイルパス(
references/、../ln-*)は、このスキルディレクトリを基準とした相対パスです。
クエリ効率監査(L3 ワーカー)
種類: L3 ワーカー
データベースクエリのパターンを対象に、冗長性、非効率性、誤用を監査する専門ワーカーです。
目的と範囲
- クエリ効率を監査します(優先度:高)
- 冗長なフェッチ、バッチ操作の誤用、キャッシュのスコープに関する問題を確認します
- 重大度、場所、作業量、推奨事項を含む構造化された指摘をファイルに出力します
- クエリ効率カテゴリの適合スコア(X/10)を算出します
入力
必須の読み込み: references/audit_worker_core_contract.md と references/mcp_tool_preferences.md を読み込みます。
ツールのポリシー:ホストの AGENTS.md が適用範囲外の独立したサブエージェントとして実行される場合があるため、ファイルの読み取り、検索、編集では hex-line MCP を優先します。MCP の動作が不明確な場合に限り、references/mcp_integration_patterns.md を読み込みます。
tech_stack、best_practices、db_config(データベースの種類、ORM の設定)、codebase_root、output_dir を含む contextStore を受け取ります。
ドメイン対応: domain_mode と current_domain をサポートします。
参照チェーンや呼び出し経路がクエリ分析に大きく役立つ場合は、最初に hex-graph を使用します。ローカルのコードや設定の読み取りでは、利用可能な場合、最初に hex-line を使用します。MCP が利用できない、未対応、またはインデックス未作成の場合は、組み込みの Read/Grep/Glob/Bash を使用して続行し、レポートにフォールバックを明記します。
ワークフロー
検出ポリシー:2 層の検出(候補のスキャン、その後のコンテキスト検証)を使用します。検証方法が不明確な場合に限り、references/two_layer_detection.md を読み込みます。
-
contextStore からコンテキストを解析する
- tech_stack、best_practices、db_config、output_dir を抽出します
- scan_path を決定します(ln-624 と同じロジック)
-
コードベースをスキャンして違反を検出する
- すべての Grep/Glob パターンで
scan_pathを使用します - 冗長なフェッチを調べるために、呼び出しチェーンを追跡します(呼び出し元と呼び出し先の読み取りが必要です)
- すべての Grep/Glob パターンで
-
重大度、場所、作業量、推奨事項を含む指摘を収集する
-
ペナルティアルゴリズムを使用してスコアを算出する
-
レポートを作成する:
references/templates/audit_worker_report_template.mdに従って完全な Markdown レポートをメモリ上で構築し、単一の Write 呼び出しで{output_dir}/ln-651--global.mdに書き込みます -
概要を返す: コーディネーターに最小限の概要を返します(出力形式を参照)
監査ルール(優先度:高)
1. エンティティの冗長なフェッチ
内容: 呼び出しチェーン内で、同じエンティティがデータベースから 2 回取得されます
検出方法:
repo.get(id)またはsession.get(Model, id)を呼び出した後、オブジェクトではなくidを関数 B に渡す関数 A を探します- 関数 B も同じエンティティについて
repo.get(id)またはsession.get(Model, id)を呼び出していることを確認します - 典型的なパターン:
acquire_next_pending()がジョブを返す一方、_process_job(job_id)がそのジョブを再取得します
検出パターン(Python/SQLAlchemy):
- サービス/ハンドラーファイルで
repo.*get_by_id|session\.get\(|session\.query.*filter.*idを Grep で検索します - 呼び出しを追跡します:関数が
entity_id: int/UUIDを受け取り、内部でrepo.get(entity_id)を呼び出している場合、呼び出し元がすでにエンティティオブジェクトを取得していないか確認します expire_on_commitの設定を確認します:Falseの場合、コミット後もオブジェクトは有効なままです
重大度:
- 高: API リクエストハンドラーでの冗長なフェッチ(リクエストごとに遅延が増加します)
- 中: バックグラウンドジョブでの冗長なフェッチ(重要度は比較的低くなります)
- 引き下げる場合: 初期化/マイグレーションコードでのフェッチ(1 回のみ実行)→ 低。管理者専用のトラフィックが少ないエンドポイントは、1 段階引き下げます
推奨事項: ID の代わりにエンティティオブジェクトを渡すか、expire_on_commit=False の場合は 2 回目のフェッチを削除します
作業量: S(オブジェクトを受け取るようにシグネチャを変更)
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_)が続くものを Grepfor .* in .*:の後 1〜3 行以内にsession\.execute\(.*update\(が続くものを Grep
重要度:
- HIGH: 10 件を超えるアイテムのループ (DB への N 回の個別ラウンドトリップ)
- MEDIUM: 10 件以下のアイテムのループ
- ダウングレード条件: ブートストラップ/マイグレーションコード内のループ (一度だけ実行) -> LOW。管理者専用エンドポイント -> 1 段階ダウングレード
推奨: 単一の UPDATE ... WHERE id IN (...) または session.execute(update(Model).where(Model.id.in_(ids))) に置き換える
工数: M (クエリの書き換え + テスト)
3. 不要な Resolve
内容: 呼び出し元のスコープですでに利用可能な値を DB から再解決している
検出:
- メソッドが
profile_idを受け取り、そこからエンジンを解決しているが、呼び出し元はすでにengineを特定している - メソッドが
lang_codeを受け取り、dialect_id を検索しているが、呼び出し元はすでにlangとdialectの両方を持っている - パターン: 関数が
X_idを受け取り、get(X_id)を実行して.fieldを抽出しているが、呼び出し元はすでにfieldを持っている
重要度:
- MEDIUM: 呼び出しごとに余分な DB クエリが発生する。特に高頻度のパスにおいて
推奨: メソッドを 2 つのバリアントに分割する: with_known_value(value, ...) と resolving_value(id, ...)。または解決済みの値を直接渡す
工数: S-M (シグネチャのリファクタリング、呼び出し元の更新)
4. 過剰フェッチ
内容: 少数のフィールドしか必要としないのに、ORM モデル全体をロードしている
検出:
- 列数が 10 を超えるモデルに対して
.options(load_only(...))なしでsession.query(Model)またはselect(Model)を実行している - 特に多数の行を返すリスト/検索エンドポイントにおいて
- パターン: エンティティ全体をロードしているのに 2〜3 フィールドしか使用していない
重要度:
- MEDIUM: リストエンドポイントにおける大規模モデル (15 列超)
- LOW: 小規模モデル (10 列未満) または単一エンティティのエンドポイント
推奨: リストクエリには load_only()、defer()、または生の select(Model.col1, Model.col2) を使用する
工数: S (クエリに load_only を追加)
5. バルク操作の欠如
内容: バルク操作ではなく、逐次的な INSERT/DELETE/UPDATE を実行している
検出:
session.add_all(items)ではなくfor item in items: session.add(item)- バルク削除ではなく
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 >> リクエストの所要時間 (例: エンジン設定、言語リスト、フィーチャーフラグ)
検出パターン:
_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