mcpField
D
database-schema-design

database-schema-design

github.com/pixel-process-ugデータ・データベース384 回インストール33 週間前に更新
リポジトリ

database-schema-design について

要件整理からモデリング、インデックス、マイグレーション計画までを扱うデータベース設計スキルです。段階的なレビューを通じて、正規化、計測に基づく最適化、ロールバック可能な変更を支援します。

主な機能

  1. 01要件整理と概念モデリング
  2. 02論理スキーマと関係の設計
  3. 03インデックスとクエリ最適化の指針
  4. 04Expand-Contract による移行計画
  5. 05ORM とコネクションプーリングの指針

活用シーン

  1. 01実装前のエンティティと関係の整理
  2. 02クエリパターンに基づくインデックス選定
  3. 03安全なスキーマ変更とデータ補完の計画

インストール

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

$npx skills add https://github.com/pixel-process-ug/superkit-agents --skill database-schema-design

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

詳細

データベーススキーマ設計

概要

適切なデータモデリング、安全なマイグレーション、効果的なインデックス作成、適切なクエリパターンに基づいて、データベーススキーマの設計、実装、最適化を行います。このスキルでは、概念モデリングから物理設計の最適化まで、ライフサイクル全体を扱い、正規化され、パフォーマンスに優れ、安全に進化できるスキーマを実現します。

開始時に伝えます:「データベーススキーマを設計するため、database-schema-design スキルを使用します。」

フェーズ 1:要件の把握と概念モデル

データ要件を理解するため、次の質問をします。

#質問判断できること
1システムが管理するエンティティは何ですか?テーブル名
2エンティティ間にはどのような関係がありますか?外部キー、中間テーブル
3各エンティティの主要な属性は何ですか?列の定義
4主なクエリパターンは何ですか?インデックス戦略
5想定されるデータ量はどのくらいですか?(行数、増加率)パーティショニング、スケーリング
6読み取りと書き込みの比率はどのくらいですか?正規化と非正規化の選択
7SQL と NoSQL のどちらを使いますか?(または両方ですか?)ストレージエンジンの選択
ストレージエンジンの選択表
要素SQL を選択(PostgreSQL、MySQL)ドキュメント型を選択(MongoDB)キー・バリュー型を選択(Redis)
データの形式構造化データ、リレーショナルデータ半構造化データ、ネストされたデータ単純な検索、キャッシュ
クエリの複雑さ複雑な結合、集計ドキュメント単位のクエリキーによるアクセスのみ
一貫性の要件ACID が必須結果整合性で問題なし一時的なデータ、またはキャッシュデータ
スキーマの進化マイグレーションで管理可能スキーマに縛られない柔軟性スキーマなし
スケーリングのパターンまず垂直スケーリング、その後に読み取りレプリカ水平シャーディングインメモリ、サイズに制限あり

要件の把握後は停止し、確認のため概念モデル(エンティティ、関係、カーディナリティ)を提示します。

フェーズ 2:論理モデルの設計

概念モデルをテーブル、列、型、制約に落とし込みます。

列設計のルール
判断項目指針
主キー分散システムでは UUID、単一ノードでは自動採番を使用します
列の型最も具体的な型を使用します(日付には varchar ではなく timestamptz)
NULL 許容デフォルトは NOT NULL とし、値がないことに意味がある場合に限り NULL を許可します
デフォルト値適切なデフォルト値を設定します(created_at DEFAULT now())
制約CHECK、UNIQUE、FK 制約をスキーマレベルで追加します
命名snake_case を使用し、テーブル名は単数形か複数形のどちらかに統一します
正規化ガイド
正規形ルール違反例修正方法
1NF値は原子性を持ち、繰り返しグループがないtags VARCHAR "urgent,priority,vip"order_tags テーブルを分けます
2NFすべての非キー列が主キー全体に依存する複合主キーを持つ order_items 内の product_nameproducts テーブルに移します
3NF推移的な関数従属がないcity は user_id ではなく zip_code に依存するzip_codes テーブルを分けます

ルール: まずは常に正規化します。測定結果に基づく根拠がある場合にのみ、非正規化します。

非正規化の判断表
シナリオパターン適用するタイミング
読み取りが多いダッシュボードマテリアライズドビューまたはサマリーテーブルクエリの遅さが測定された場合
頻繁に結合するデータJSONB 列に埋め込みますクエリ時間の 80% 超を結合が占める場合
レポート/分析非正規化したレポート用テーブルを分けますOLAP ワークロード
キャッシュ層書き込み時に更新する計算済み列高頻度の読み取り
リレーションシップのパターン
リレーションシップ実装必要なインデックス
1 対 1子テーブルに UNIQUE 制約付きの FKFK 列
1 対多「多」側に FKFK 列
多対多複合 PK を持つ中間テーブル/結合テーブル両方の FK 列
ポリモーフィックCHECK 制約付きの個別の FK 列(推奨)、または type+id パターンtype+id または各 FK
自己参照(ツリー)同じテーブルを参照する parent_id FK、または ltree/マテリアライズドパスparent_id またはパス

論理モデルの段階で停止し、レビュー用にテーブル定義を提示してください。

フェーズ 3:物理モデルとインデックス作成

インデックスタイプの選択表
インデックスタイプ最適な用途例
B-tree(デフォルト)等価検索と範囲検索CREATE INDEX idx_users_email ON users(email)
GIN全文検索、JSONB、配列CREATE INDEX idx_posts_search ON posts USING GIN(to_tsvector('english', body))
部分インデックス条件に一致する行のサブセットCREATE INDEX idx_active_users ON users(email) WHERE active = true
カバリング(INCLUDE)テーブル参照を避けるインデックスのみのスキャンCREATE INDEX idx_users_email ON users(email) INCLUDE (name)
複合インデックス複数列に対するクエリCREATE INDEX idx_orders ON orders(tenant_id, status)
複合インデックスの列順
位置列のタイプ理由
先頭カーディナリティの高い等価条件の列最も選択性の高いフィルターを先頭にする
中間追加の等価条件の列結果をさらに絞り込む
末尾範囲条件の列(日付、数値)残りの行に対して範囲スキャンを行う

ルール: (A, B, C) の複合インデックスは、A、A+B、A+B+C に対するクエリをサポートしますが、B 単独または C 単独はサポートしません。

クエリ最適化チェックリスト
EXPLAIN ANALYZE のシグナル問題修正方法
大規模テーブルでの Seq Scanインデックスがない適切なインデックスを追加する
外側のテーブルが大きい Nested Loop結合が非効率インデックスを追加するか、クエリを再構成する
実際の行数と推定行数の差が大きい統計情報が古いテーブルに対して ANALYZE を実行する
Hash Join のメモリ使用量が大きいwork_mem が小さすぎるwork_mem を調整するか、クエリを再構成する
N+1 の検出と防止
-- N+1 problem (bad):
SELECT * FROM users;
-- Then for EACH user: SELECT * FROM orders WHERE user_id = ?;

-- Fixed with join:
SELECT u.*, o.* FROM users u LEFT JOIN orders o ON o.user_id = u.id;

-- Fixed with batch load:
SELECT * FROM orders WHERE user_id = ANY($1);

物理モデルの段階で停止し、インデックスと最適化戦略をレビュー用に提示してください。

フェーズ 4:マイグレーション戦略

ゼロダウンタイムマイグレーション(拡張・縮小)

1 つのマイグレーションで破壊的変更を行わないでください。2 つのフェーズに分けてください。

拡張フェーズ(後方互換性あり):

  1. 新しい列/テーブルを追加する(NULL 許容、またはデフォルト値を設定)
  2. 古い列と新しい列の両方に書き込むコードをデプロイする
  3. 既存データをバッチ処理でバックフィルする
  4. 新しい列から読み込むコードをデプロイする

縮小フェーズ(すべてのコードが新しいスキーマを使用した後):

  1. 古い列への書き込みを行うコードを削除する
  2. 古い列/テーブルを削除する
マイグレーションの安全性ルール
ルール理由
すべてのマイグレーションに対応するロールバックを用意する安全に元に戻せる
本番環境に適用する前にステージング環境でロールバックをテストする元に戻せることを確認する
データを破壊するロールバックには明示的な承認が必要誤ったデータ損失を防ぐ
適用済みのマイグレーションファイルは変更しない状態を再現可能にする
大規模テーブルはバッチ(1000 行)でバックフィルするテーブルロックを回避する
バックフィルのパターン
-- Backfill in chunks of 1000
UPDATE users SET display_name = username
WHERE display_name IS NULL
AND id IN (SELECT id FROM users WHERE display_name IS NULL LIMIT 1000);
マイグレーションタイプの選択表
変更タイプ安全な方法危険な方法
列の追加NULL 許容、またはデフォルト値を設定して追加するデフォルト値なしで NOT NULL を追加する
列の削除拡張・縮小(2 回のデプロイ)列を直接削除する
列名の変更新しい列を追加し、データをコピーしてから古い列を削除するALTER RENAME(クエリが動作しなくなる)
インデックスの追加CREATE INDEX CONCURRENTLYCREATE INDEX(テーブルをロックする)
列の型の変更新しい列を追加してデータを移行するALTER COLUMN TYPE(テーブルをロックする)

マイグレーション計画の段階で停止し、最終決定の前にロールバック戦略を確認してください。

フェーズ 5:保存と移行

明示的な承認を得た後:

  1. スキーマ設計を docs/database/ に保存するか、マイグレーションファイルを生成します
  2. 次のメッセージでコミットします:docs(db): add schema design for <feature>
移行先の判断表
ユーザーの意図次のスキル理由
「マイグレーションを作成して」planningマイグレーションの実装を計画します
「これの仕様を書いて」spec-writingデータ操作の振る舞いに関する仕様を作成します
「スキーマを実装して」test-driven-developmentマイグレーションテストを用いた TDD
「設計を保存するだけでいい」なしスキーマ設計が成果物です
「パフォーマンスをレビューして」performance-optimizationクエリパターンを分析します

ORM のガイダンス

ORM言語強み注意点
PrismaTypeScript型安全なスキーマ、マイグレーションネストされたクエリでの N+1、限られた生 SQL 対応
DrizzleTypeScriptSQL に似た API、軽量エコシステムが新しく、ガイドが少ない
SQLAlchemyPython成熟しており、柔軟で、生 SQL に対応複雑なセッション管理
GORMGo規約ベース、自動マイグレーションサイレントな失敗、暗黙の動作
ORM のベストプラクティス
  • 生成された SQL は必ず確認します(開発環境でクエリログを有効にします)
  • N+1 クエリを防ぐため、イーガーローディングを使用します
  • ORM と格闘するのではなく、複雑なクエリには生 SQL を記述します
  • 本番環境では自動同期ではなく、ORM のマイグレーションを使用します
  • 現実的なデータ量でクエリのパフォーマンスをテストします

コネクションプーリング

  • コネクションプーラー(PgBouncer、組み込みプール)を使用します
  • プールサイズの計算式:connections = (CPU cores * 2) + disk spindles
  • ほとんどのワークロードでは、トランザクションレベルのプーリングを使用します
  • アプリケーションサーバーから生のコネクションを開かないようにします

アンチパターン/よくある間違い

間違い問題点代わりにすべきこと
外部キー制約がない孤立データや壊れたリレーションシップが発生します必ず FK 制約を定義します
すべてに VARCHAR を使う型安全性が失われ、ストレージを無駄にします適切な型(timestamptz、int、uuid)を使います
FK 列にインデックスがない関連テーブルの結合が遅くなりますすべての FK 列にインデックスを設定します
早すぎる非正規化効果が測定されていないのに複雑さが増します正規化した状態から始め、根拠を確認して非正規化します
列を直接削除する実行中のアプリケーションコードが壊れますexpand-contract パターンを使用します
CONCURRENTLY なしで CREATE INDEX を実行するインデックス作成中にテーブルがロックされます本番環境では必ず CONCURRENTLY を使用します
本番環境でスキーマを自動同期する予測できない破壊的変更が発生します明示的なマイグレーションファイルを使用します
マイグレーションのロールバック計画がないデプロイ失敗から復旧できませんすべての up マイグレーションに対応する down マイグレーションを記述します
どの列も NULL 許容にするデータ整合性の保証が失われますデフォルトは NOT NULL とし、意図的に NULL を許可します

非合理化を防ぐためのガード

  • 概念モデルを省略してはいけません — まずエンティティとリレーションシップを把握します
  • 推測でインデックスを追加してはいけません — まずクエリパターンを測定します
  • パフォーマンス上の問題があるという測定結果なしに、非正規化してはいけません
  • ロールバック計画なしにマイグレーションを作成してはいけません
  • 調査フェーズを省略してはいけません — クエリパターンとデータ量を把握します
  • 本番環境で expand-contract パターンを使わずに列やテーブルを削除してはいけません

ドキュメントの参照(Context7)

最新のドキュメントを参照するには、mcp__context7__resolve-library-id の後に mcp__context7__query-docs を使用します。返されたドキュメントは、記憶している知識より優先されます。

  • prisma — スキーマ構文、リレーション、マイグレーション API を確認する場合
  • typeorm — エンティティデコレーター、リポジトリパターン、クエリビルダーを確認する場合
  • knex — クエリビルダー構文、マイグレーション、シードファイルを確認する場合

統合ポイント

スキル関係
api-design上流:API リソースはデータベースエンティティに対応します
spec-writing上流:仕様書でデータ永続化の要件を定義します
planning下流:スキーマ設計が実装計画に反映されます
test-driven-development下流:マイグレーションコードを書く前に、マイグレーションテストを作成します
performance-optimization下流:スキーマの稼働後にクエリを最適化します
reverse-engineering-specs上流:既存のスキーマの動作をリバースエンジニアリングします
senior-backend並行:ORM とクエリパターンを担当するバックエンドのスペシャリストです

検証ゲート

スキーマ設計が完了したと宣言する前に、以下を確認します。

  1. すべてのエンティティとリレーションシップがモデル化されていることを確認します
  2. 正規化が少なくとも第 3 正規形(3NF)であること(または非正規化が正当化されていること)を確認します
  3. すべてのクエリパターンと FK 列に対するインデックスが定義されていることを確認します
  4. マイグレーション戦略に、すべてのステップのロールバックが含まれていることを確認します
  5. ユーザーがスキーマ設計を承認していることを確認します
  6. 本番環境向けのコネクションプーリング戦略が定義されていることを確認します

スキルの種類

柔軟 — 概念モデルから物理モデルへの移行、マイグレーションの安全性に関するルール、非正規化の前に測定済みのエビデンスを求める原則を保ちながら、ストレージエンジン、正規化のレベル、インデックス戦略をプロジェクトのニーズに合わせて調整します。

コメント