シリーズ: 要件定義とはそもそも何か
- 要件定義の目的とゴールとは
- 要件定義の重要ポイント〜要望・要求・要件を見極める
- 事業・業務・システムの3階層で要件を捉える
- 業務フロー図で見える化する業務プロセスからシステム要件への道筋
- ユースケースとロバストネス図によるシステム要件定義
- システム要件定義の成果物〜設計へのインプットを作成する
- 要件定義とソフトウェアアーキテクチャ設計
- 要件定義とクラス設計
- 要件定義とデータベース設計(本記事)
TRACERYプロダクトマネージャーの haru です。
システムとは、ヒト・モノ・カネ・情報といった経営資源が有機的に連携し、共通の目的に向かって動く仕組みです*1。
ソフトウェアはこの連携を処理の振る舞いとして実装し、システム内でのやり取りをデータとして記録します。
したがって、データモデル*2を確認すれば、そのシステムがどのような情報を扱い、どの情報同士が結びつき、何を中核として業務が構成されているのかが明確になります。
構造に一貫性がなく複雑なデータベースは、開発者が仕様を把握しにくく、テーブルの選定やデータ処理の記述に迷いが生じやすくなるため、結果として開発生産性の低下につながります。
データベースの整合性が考慮されていない設計では、矛盾や欠落を含んだデータが蓄積されやすくなり、システムの誤動作や業務判断の誤りといった重大なリスクを招くおそれがあります。
そのため、システムを効率よく開発し、安定的かつ持続的に運用していくには、構造が明確で、意味や整合性に優れたデータベース設計が不可欠です。
本記事では、データベース設計の進め方と、要件定義の成果物をどのように設計へ反映するかを解説します*3。
アプリケーションとデータベースで異なる設計視点
オブジェクト指向でアプリケーションを開発する場合、システムが扱うデータの構造や関係は、クラスとして設計されます*4。
クラス図とデータベース設計に用いられることが多いER図は構造がよく似ているため、「クラス図(ドメインモデル)があれば、あえてデータベース設計を行う必要はないのではないか」と考えられがちです。
しかし、アプリケーションとデータベースでは、データに対する役割や設計上の関心が根本的に異なります。
アプリケーションの関心事は「データをどう処理するか」(入力検証、業務ロジック、画面反映など)です。
一方で、データベースの関心事は「データをどう保存し、矛盾なく維持するか」(永続化*5と構造的整合性)です。
アプリケーション側のバリデーションに不備があれば誤った値がそのまま永続化される恐れがあります。また、システム障害時などにSQLで直接データパッチを適用した場合、不整合なデータが登録・更新されるリスクもあります。
そのようなリスクを避けるため、データベース側でも、主キー・外部キー・一意制約・NOT NULL などを設けて整合性を保証し、データ品質を担保する必要があります。
性能に関しても、アプリケーションとデータベースでは設計の視点が異なります。
アプリケーションは、ユーザー操作への応答性や画面遷移の体感速度など、処理の流れとタイミングに着目します。
一方、データベースは、大量データの検索・集計を高速化するために、インデックスの設計や正規化・非正規化のバランス、クエリの実行計画などに注目します。
データベース設計の不備は、システム全体に影響を及ぼす
データベース設計の不備は、システムのあらゆる側面に波及します。
データの整合性が崩れ、処理が正しく行えなくなるだけでなく、開発の手戻りや運用中の性能問題といった形で表面化することもあります。
こうした事態を防ぐには、アプリケーションとは異なる観点から、データ構造や制約をあらかじめ設計し、システム全体の堅牢性を確保しておくことが重要です。
以下では、データベース設計の不備が引き起こす代表的な問題とその影響について説明します。
データの不整合が発生する
データの整合性はシステムが健全に動作するための土台です。データの整合性が崩れると、システム全体が論理的に破綻してしまいます。
たとえば、データの重複や想定外の値、関連性の欠如といった不整合があると、処理の前提が崩れ、意図通りに機能しなくなります。
その結果、各所で不具合が発生し、安定したサービスの提供が難しくなります。
ソフトウェア開発の生産性と品質が低下する
データの意味や関係があいまいなままだと、開発者は実装のたびに「どのテーブルを参照すべきか」「この項目の用途は何か」を毎回調べて判断する必要があります。
設計の意図が共有されていないことで、開発者ごとに異なる解釈で実装が進み、その結果、統一感のないコードや設計方針とずれた構造が生まれやすくなります。
こうした状態では、保守や機能追加のたびに意図の確認や修正に時間がかかり、手戻りによって開発スピードと品質が損なわれます。
運用後に性能劣化が表面化し、改修コストが増大する
正規化の不備やインデックスの不足は、当初は見過ごされがちですが、運用が始まるとレスポンスの悪化やバッチ処理の遅延といった深刻な性能問題として顕在化します。
運用後にインデックスを追加する場合は、本番環境への影響を避けるために、リリースのタイミングや適用手順を慎重に調整する必要があります。
インデックスの追加だけでは対応しきれないケースでは、テーブル構造そのものの見直しが必要になることもあります。
その変更はアプリケーション全体に波及し、大規模な修正コストとリスクを伴います。
要件定義の成果物とデータベース設計の連携
では、こうした観点を踏まえて、実際にどのようにデータベース設計を進めていけばよいのでしょうか。
機能要件とデータベース設計の連携
要件定義とクラス設計 - TRACERY Lab.(トレラボ)で説明したように、要件定義で作成された機能要件に関する成果物(概念モデル、機能要件の記述、状態遷移図)は、クラス設計に反映されます。そして、そのクラス設計をもとにデータベースの構造が設計されていきます(下図)。
このように、機能要件はデータベース設計に直接現れるわけではありませんが、クラス設計を介して間接的に関係しています。そのため、機能要件の意図が正しくデータベースにまで反映されているかを確認することが重要です。
とくに、テーブル構造や属性の有無、リレーションの設計が、業務のルールと整合しているかどうかは、データベース設計で丁寧に見直す必要があります。
クラス図からテーブル構造への変換と設計上の注意点
クラス設計をもとにテーブルを設計する場合、多くのケースでクラスとテーブルは1対1で対応し、クラスの属性はテーブルのカラム、クラス間の関連はテーブル間のリレーション(外部キー)としてマッピングされます。
以下は、要件定義とクラス設計 - TRACERY Lab.(トレラボ)で取り上げたクラス図をもとに、データベース設計へとマッピングした例です。
このように、クラス図は一見、そのままテーブル定義に変換できるように見えます。
しかし、クラス図の構造をそのまま写し取っただけでは、パフォーマンスを確保するための適切な永続化が行えない場合があります。
その背景には、クラスでは柔軟に扱える複雑な構造も、表形式のリレーショナルデータベースではそのままでは表現できず、構造を分割したり関係を明示したりする設計上の工夫が必要になる点があります。
以下の表に、クラス設計とデータベース設計における永続化の観点での主な違いをまとめました。
観点 | クラス設計 | データベース設計 |
---|---|---|
多対多の関係の表現 | コレクション型(List やSet など)で自然に表現可能 |
中間テーブルを明示的に設計・管理する必要がある |
柔軟な構造の表現(配列・Map・ネストなど) | 言語機能で柔軟に表現可能 | 表形式に合わせた分割、正規化、またはJSON列などの対応が必要 |
ネストの参照・参照チェイン*6 | オブジェクト参照でスムーズにアクセスできる | 複数テーブルのJOINやネストされたクエリが必要になり、性能や可読性が低下しない設計が必要 |
継承構造の表現 | クラスの継承関係を言語機能で直接定義・再利用できる | 単一テーブル継承、クラスごとのテーブル分割、親子テーブルの結合型など複数の方式があり、選択と実装に工夫が必要 |
このミスマッチを理解せずにクラス設計をそのままデータベースに反映すると、正規化されていないテーブル、複雑なJOINの乱用、整合性を欠いた設計などが生じ、データ構造の破綻や保守性の低下、性能劣化、データ品質の不安定化といった深刻な問題を引き起こします。
リリース初期は問題なく動作していても、後から構造的な欠陥が表面化するリスクは高くなります。
したがって、クラス設計とデータベース設計の役割や前提の違いを正しく理解し、それぞれの責務に応じて設計を調整・補強する必要があります。
コラム:データベース設計からアプリケーション設計を進めるアプローチ
前の節では、クラス設計を起点にデータベース設計へ展開する方法を解説しました。
これとは逆に、データベースを先に設計し、その後でアプリケーションを組み立てる手法もあります。これは DOA(Data Oriented Approach:データ中心アプローチ) と呼ばれ、設計上の有力な選択肢です。
一方、クラス(オブジェクト)を出発点に設計を進める手法は OOA(Object‑Oriented Approach:オブジェクト指向アプローチ) と呼ばれます。
DOA と OOA の詳細な比較は一記事では扱いきれないため、別の記事で説明します。
非機能要件とデータベース設計の連携
非機能要件は下図*7に示す要素で構成されます。
データベース設計では、これらの非機能要件のうち、データ品質、性能効率、セキュリティ、保守性に着目します。
データ品質とデータベース設計
データ品質は ISO/IEC 25012:2008 *8において、「妥当性」「一貫性」「信頼性」「正確性」など12のサブ特性に分類されています。概要を次の表に示します。
特性名 | 説明 |
---|---|
正確性(Accuracy) | データが事実と一致しているか |
完全性(Completeness) | 必要なデータが欠けていないか |
一貫性(Consistency) | データ間に矛盾がないか |
信憑性(Credibility) | データの出所が正当か。改ざんされていないか |
最新性(Currentness) | データが最新か |
アクセシビリティ(Accessibility) | データが誰でも使用できるものになっているか |
標準適合性(Compliance) | データの書式は標準に準拠しているか。使用している文字セットは正しいか。選択項目に、指定された選択肢以外のデータが入っていないか。 |
機密性(Confidentiality) | データが許可された人だけに開示されているか |
効率性(Efficiency) | データが冗長でなく、必要な処理に適したフォーマットになっているか |
精度(Precision) | データが必要な精度(桁数や単位)で記録されているか |
追跡可能性(Traceability) | データの由来や変更履歴をたどることができるか |
理解性(Understandability) | データの意味や構造がユーザーにとって分かりやすいか |
可用性(Availability) | 必要なときにデータが利用可能な状態にあるか |
移植性(Portability) | データが他の環境やシステムに移行しやすいか |
回復性(Recoverability) | データ損失や障害発生時に迅速に復旧できるか |
以下の表は、各サブ特性をデータベース設計に落とし込む際の具体策をまとめたものです。
これらの観点はクラス図(ドメインモデル)には表れにくく、設計段階で見落とされやすいポイントです。システムの特性や運用条件を踏まえ、必要な制約と構造を確実に組み込む必要があります。
これらの観点を設計段階で取り入れることで、データの正確性と安全性を高め、将来の機能追加や分析業務にも柔軟に対応できるデータ基盤を構築できます。
サブ特性 | データベース設計での反映例 |
---|---|
正確性(Accuracy) | 入力値に対する制約(例:CHECK制約)、正規化による意味の明確化 |
完全性(Completeness) | NOT NULL制約、外部キーによるリレーションの存在保証 |
一貫性(Consistency) | 外部キー制約、トランザクション制御(ACID特性) |
信憑性(Credibility) | データ出所を格納するカラムの用意、改ざん検知用のハッシュ値をデータに保持する。 |
最新性(Currentness) | データの更新時刻を記録するカラムを設け、最新データのみを識別・抽出できるように設計する |
アクセシビリティ(Accessibility) | 多様な利用者や支援技術に配慮し、文字コードの統一や、わかりやすく機械可読な項目設計を行う |
標準適合性(Compliance) | 形式や値が標準ルールに従うよう、文字コード・日付・コード体系を統一して設計する |
機密性(Confidentiality) | アクセス制御(GRANT/REVOKE)、テーブル単位の権限設定 |
効率性(Efficiency) | データが無駄に重複せず、必要以上に肥大化せず、用途に応じて処理しやすい構造や粒度で格納されるように設計する |
精度(Precision) | 数値や日時の桁数指定、FLOAT vs DECIMALの使い分け |
追跡可能性(Traceability) | ログテーブルの設計、履歴テーブル(*_history )の導入 |
理解性(Understandability) | 命名規則の統一、コメント定義の活用、ER図の作成 |
可用性(Availability) | 冗長構成(レプリケーション)、バックアップポリシーの設計 |
移植性(Portability) | データ形式や値の表現が特定システムに依存せず、他環境でも意味や構造が保たれるように設計する |
回復性(Recoverability) | バックアップ設計、トランザクションログの活用、障害復旧シナリオの準備 |
性能効率とデータベース設計
性能効率に関する性能要件には、たとえば「検索結果を3秒以内に返す」「1秒あたり100件の書き込みを処理する」といった具体的な数値指標が設定されるのが一般的です。これらの要件を満たすためには、アプリケーションコードの最適化に加え、データベースの構造自体にも十分な配慮が求められます。
まず重要なのは、アクセス頻度の高いデータをどのように配置し、どのようにインデックスを設計するかという点です。
たとえば、検索条件に頻繁に使われるカラムに対して適切なインデックスが設定されていなければ、どれだけアプリケーション側の処理が高速であっても、レスポンス全体は遅くなってしまいます。
また、データの正規化と非正規化のバランスも性能に大きく影響します。
正規化によって冗長なデータを排除することはデータの整合性を保つうえで有効ですが、過度な正規化は結合処理の増加を招き、パフォーマンスを劣化させる要因にもなります。
性能要件が厳しいケースでは、非正規化を取り入れて冗長性を許容しつつ、読み取りの高速化を優先する判断も必要です。
さらに、データのライフサイクルを考慮した設計も欠かせません。古いデータをアーカイブする、あるいはアクセス頻度の低いデータを別テーブルに分離することで、実運用時のパフォーマンスを維持しやすくなります。
このように、性能要件を満たすためには、単にデータベースを「正しく」設計するだけでなく、「現実の使われ方」を想定したうえで最適化する視点が求められます。
セキュリティとデータベース設計
データベースはもっとも攻撃対象となりやすい部分のひとつです。
とくに、個人情報や認証情報といった機密性の高いデータを扱う場合、その漏えいが事業に与えるダメージは計り知れません。
こうしたリスクに備えるには、アプリケーションレイヤーの対策だけでなく、データベース設計そのものにセキュリティの視点を織り込むことが欠かせません。
まず代表的な対策として、ユーザーのパスワードをハッシュ化して保存する方法があります。
また、単なるハッシュ関数だけでなく、ソルトやストレッチング(PBKDF2、bcrypt、Argon2 など)を組み合わせることで、辞書攻撃や総当たり攻撃への耐性を高めることができます。
一方で、パスワード以外の機密情報、たとえばクレジットカード番号やマイナンバーといった「復号が必要なデータ」については、暗号化処理が求められます。
暗号鍵の管理や鍵のローテーションも含めた設計が重要であり、アプリケーション側の責務とデータベース側の責務を明確に切り分ける必要があります。
さらに、データベース全体を対象とした「透過的暗号化(TDE)」は、物理媒体の盗難やディスクイメージの不正取得といった低レイヤの攻撃に備える有効な手段です。
ファイルシステムレベルで暗号化されるため、アプリケーションには変更を加えずにセキュリティを強化できます。
このように、セキュリティとデータベース設計は切っても切り離せない関係にあります。
「暗号化していれば安全」という単純な話ではなく、何を守るべきか・誰から守るべきかを明確にした上で、設計・実装の段階からセキュリティを組み込む姿勢が求められます。
保守性とデータベース設計
テーブル名やカラム名の意味が不明瞭だったり、似たような情報が複数の場所に散らばっていたりすると、改修や運用のたびに設計の意図を探る作業が必要になり、保守にかかる負荷が増していきます。
こうした状況の多くは、設計時の命名や構造に対する配慮が不足していることに起因しています。
特に命名は、設計の意図を他の開発者に伝えるための基本的なインターフェースです。たとえば、uid
や ref_no
のような略称が使われていると、その意味や用途を都度確認する必要が生じます。
一方で、user_id
や reference_number
のように明確で一貫性のある名前であれば、スキーマ全体の理解が容易になり、保守作業のスピードと正確性が向上します。
構造面でも、用途の異なるデータをひとつのテーブルに詰め込んでいたり、結合関係が過剰に複雑化していたりすると、影響範囲の見通しが立ちにくくなります。
こうした構造は、変更のたびに予期しない不具合を引き起こしやすく、結果として改修コストを高めてしまいます。
このように、命名と構造のわかりやすさは、初期実装の効率だけでなく、長期的な運用・改修における安定性や生産性を大きく左右します。
まとめ
下図に、要件定義の成果物とデータベース設計の関係をまとめました。
本記事では、クラス設計とデータベース設計の関係を踏まえ、信頼性の高いデータベースを構築するための基本的な考え方を解説しました。
アプリケーションと同様に、データベースにも独立した責務と視点が求められます。
クラス設計をそのままテーブル定義へ写し取るだけでは、パフォーマンスを確保するための適切な永続化が行えない場合があります。
さらに、データベース設計は構造だけでなく、非機能要件を満たす必要があります。
設計段階で「データをどう扱い、どう守るか」を意識することで、運用後の改修コストを抑え、システムの保守性と信頼性を高められます。
データは企業の重要な資産です。この資産を最大限に活用し、事業の成長を支えるシステムを実現するためにも、アプリケーション設計と並行してデータベース設計にも十分な時間と工夫を注ぎましょう。
*1: システム開発におけるシステムとは何か - TRACERY Lab.(トレラボ)を参照のこと。
*2:システムで扱う情報(データ)の種類や構造、およびデータ同士の関係性を整理・定義した設計図のこと。たとえば「顧客」「注文」「商品」といった情報が、どのような属性を持ち、どのように関連し合うかを表現する。
*3:システム開発で最も一般的に使用されているリレーショナルデータベースを前提に説明する。
*4: シリーズ前回の記事、要件定義とクラス設計 - TRACERY Lab.(トレラボ)を参照のこと。
*5:アプリケーションが扱うオブジェクトの状態は実行中だけでなく、最終的にデータベースへ保存される。この保存処理を「永続化」と呼ぶ。
*6:オブジェクトやテーブルなどが複数の中間要素を介して間接的に参照し合っている状態
*7:図は(REBOK(Requirements Engineering Body Of Knowledge:要求工学知識体系)の「1.3 機能要求と非機能要求」をもとに筆者が作成。
*8:ISO/IEC 25000シリーズの1企画。ISO/IEC 25000シリーズは、ソフトウェア製品の品質を評価・管理するための国際規格群であり、品質要求や評価手法に関する一連の基準を体系的に定めたもの。ISO/IEC 25012は、データ品質を評価・管理するための国際規格。JISではJIS X 25012:2013として規格化されている。データ品質のチェックポイントの参考資料:デジタル庁が作成したデータ品質管理ガイドブック