mcpField
D
db-query-patterns

db-query-patterns

github.com/hainrixzデータ・データベース2170 回インストール3 日前に更新
リポジトリ

db-query-patterns について

db-query-patternsは、ORMソースと生SQLのクエリ形状を調べるデータベース監査スキルです。性能に影響し得るアクセスパターンを見つけ、静的な検出結果は実行計画で確認されるまで傾向として扱います。

主な機能

  1. 01ホットパスのSELECT *を検出
  2. 02構造的なN+1クエリを検出
  3. 03深いOFFSETページングを検出
  4. 04非SARGableな述語を特定
  5. 05EXPLAINによる検証方法を提示

活用シーン

  1. 01ORMとSQLの非効率なクエリ形状の確認
  2. 02深くなるほど遅くなるページングの特定
  3. 03実行計画によるクエリ問題の検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/hainrixz/claude-db --skill db-query-patterns

インストール後、Claude Code で/db-query-patternsを入力して読み込まれたか確認します。

詳細

db-query-patterns (M13)

クエリの書き方によって、M11 のインデックスを使用できるかどうかが決まります。このモジュールでは、ORM のソースコードと生の SQL におけるクエリの形を調べます。パフォーマンスとスケーラビリティスコア(軸 performance、リレーショナルの Query w18、M3/M19 と共通)に反映されます。

チェック項目

  1. SELECT * — すべての列を取得すると、カバリングインデックスの効果が損なわれ、ネットワークやキャッシュを圧迫し、コードが列の順序に依存します。頻繁に実行される処理で検出します。
  2. 構造上の N+1 — ループ内のクエリ、または単一の JOIN やバッチ処理の IN 句にすべき、行ごとの遅延リレーション読み込みです。静的検出では方向性のみを示します(ループの実行時の件数は不明です)。コード構造を指摘するにとどめ、行数を断定することはありません。
  3. OFFSET によるページネーション — LIMIT n OFFSET m はページが深くなるほど線形に遅くなります。深いページの取得にはキ​​ーセット/シーク方式(WHERE id > $last ORDER BY id LIMIT n)を使用してください。
  4. SARG 不可能な述語 — インデックス対象の列を関数で囲む(WHERE lower(email)=…、WHERE date(created_at)=…、先頭ワイルドカードの LIKE '%x'、暗黙の型キャスト)と、インデックスを使用できません。式インデックスの作成、または述語の書き換えを推奨します。先頭ワイルドカードの LIKE '%x%' の場合、B-tree では対応できません。対処法として、列に対する pg_trgm の GIN/GiST インデックス(または、大規模な全文検索向けの専用検索エンジン)を明記します。

スコア/軸

パフォーマンスのみに反映されます(リレーショナルの Query w18、ドキュメント/時系列/グラフの各プロファイルの Query カテゴリー)。

Tier-0(静的解析)

ORM の呼び出し箇所と生の SQL を検索し、SELECT *、関数で囲まれたインデックス対象の列、先頭ワイルドカードの LIKE、OFFSET を検出します。また、N+1 の検出では、ループ内のクエリ呼び出し、.map、または各項目のリレーションアクセスを検出します。クエリパターンに関する検出結果はすべて、ソースコードから判断できるのは最大でも directional までです。実際の実行計画やコストの確認には、実行時の情報(needs_api/Tier-2)が必要です。

Tier-1/2(検証クエリ)

EXPLAIN (ANALYZE, BUFFERS) <the suspect query>;

メソッド explain_plan。インデックスが存在するのに Seq Scan が発生していれば、SARG 不可能な述語であることが確認できます。actual rows × loops から、N+1 による増幅を確認できます。Tier-2 の pg_stat_statements(total_exec_time の降順)では、実際に負荷の高いクエリを特定できます。これがない場合、負荷の高さは directional として扱います。

検出結果

schema/finding.schema.json に従って検出結果を出力します。例:

  • M13.orders.select_star_hot_path — 頻繁に実行される読み取り処理での SELECT *(severity:2、warn、軸 performance、confidence directional、fixable: proposed)。
  • M13.users.n_plus_one_posts — ループ内での行ごとのリレーション読み込み(severity:3、warn、directional、fixable: advisory — アプリ側での先行読み込み/バッチ処理が必要です)。
  • M13.feed.offset_deep_pagination — OFFSET による深いページの取得(severity:2、warn、directional、fixable: proposed — キーセット方式に書き換えます)。
  • M13.users.non_sargable_lower_email — 関数で囲まれたインデックス対象の列(severity:3、warn、directional、fixable: proposed — 式インデックス、または述語の書き換え)。

各検出結果では、evidence.observed にクエリ/呼び出し箇所をそのまま引用します(シークレットはマスキングします)。verification.reproduce には、$DATABASE_URL を参照する上記の EXPLAIN、またはパターンを検索する grep を指定します。expected_impact は、範囲と信頼度を付けて示します(根拠のないパーセンテージは禁止です)。

留意点

  • N+1 は仕様上、方向性のみを示します。ループが 2 回実行されるなら問題ありませんが、同じループが 10k 行に対して実行される場合は問題になります。静的解析ではどちらかを判断できないため、上限を設定したり、倍率を示したりすることはありません。
  • 小規模な参照処理や一度だけ実行する管理用クエリでは、SELECT * に問題はありません。重要度は、頻繁に実行される処理に限定してください。
  • 結果の意味が変わる書き換え(キーセット方式、述語の構成変更)は proposed/advisory とし、auto にはしません。式インデックスの追加は proposed にできます。

コメント