レベル: 初級 William B. Zimmerly (bill@zimmerly.com), Freelance Writer and Knowledge Engineer
2006年 11月 14日 Web ブラウザーはデータベース・スキーマで始まる行の終わりにマークを付けますが、優れたデータベース・スキーマとはどうやって作成するのでしょうか。それには効率的なツールだけではなく、計画が必要です。データベースの設計は、科学でもあり、芸術でもあります。この記事を読んで、データベースの設計手腕を磨きましょう。この記事には、高速かつ効率的で、変更にすぐに対応できるデータベース・スキーマを設計するのに役立つヒントが記載されています。
ソフトウェアの未開の地に新たに挑もうとすると、早速明らかになってくることが 1 つあります。それは、しっかりとした計画がなければ奥まで進めないということです。価値あるものを作るときはそれが何であれ、最終的な到達点を自覚し、その目標を書き留めておくことで、目標とするものを常に見失わないようにします。そしてよく言われるように、目標に近づくにつれ、重要な工程を慎重にこなしていかなければなりません。そうやって目標にたどり着いた暁には、適切に動作するシステムを作成するという感動を十分満喫できるはずです。
Apache Geronimo は標準準拠のデータベース・システムを全面的にサポートします。ただし、どんなにツールが優れているとしても、目標を達成するまでの方法をしっかりと定めた計画がなければ役に立ちません。
ヒント 1: 目標とするものを常に見据え、目標を見失ってはなりません。
Geronimo を構成する大量の Java™ クラスは、各種のツールを 1 つにまとめて機能させることによって有効なアプリケーションを作り出すように設計されています。これらのツールのなかでもとりわけ重要なのが、データベースです。データベースは複雑なため、その作成と操作には効果的な計画が欠かせません。
スキームとスキーマ
計画はピンからキリまでさまざまです。収益を最大限にするなどといったシンプルな目標を優先し、細かなことを除外した大まかで包括的な計画もあれば、コンピューター・プログラム並みの正確さを持つ厳密で具体的な計画もあります。大まかな計画は一般的にスキームとして知られ、悪い意味合いがある程度こめられています。すなわち、スキームは避けなければなりません。一方、十分な検討と作業を反映した適切かつ厳密で詳細な計画はスキーマとして知られています。
現代のデータベース技術では、さまざまなデータベース技術を支えるデータ・モデリングの名前にこの言葉を借りています。XML (Extensible Markup Language) スキーマ、データベース・スキーマ、オブジェクト・スキーマなど、プログラミングの世界では至るところでこの言葉が使われています。データベース・スキーマとは、データベースのテーブルと各テーブルのフィールドを定義する計画のことで、キー・フィールドに特に重点を置いています。このキー・フィールドを使用して、他のテーブルに含まれる追加情報の検索が行われます。
優れたスキーマは木から自然に落ちてくるわけではありません。スキーマを作成するには、調査、十分な考慮、そして規則正しいプロセスが必要です。そのすべては、目標を定義し、プロジェクト全体を通してその目標を念頭に置くということが前提となります。
密に、明確に意思の疎通をとる
このことを頭に入れた上で、何から取り掛かるのが一番よいかと言えば、あなたとあなたのカスタマーが期待している情報からです。つまり、システムがどのように使われるかを定義づけるフォームおよび情報提供の Web ページです。Geronimo はアプリケーション・コードを忠実に実行して、セッション・データとデータベース接続を維持するとともに、カスタマー (そしてカスタマーのカスタマー) が期待するページを動的に生成します。そのため、将来的な実動システムの外観とその動作方法について共通のビジョンを持つことが重要です。JSP (JavaServer Pages) テクノロジーでページをプロトタイプ化することで、自分の思い描く内容をカスタマーに示し、カスタマーからフィードバックをもらって外観を変更することが可能になります。
当たり前のことを言いますが、目標が前もって明確に定まっていなければ、とても簡単に、優れた計画に至る道を踏み外してしまいます。カスタマーに表示するビューの定義と調整には時間をかけてください。そうすることで、最終的に大きな成果をあげることができます。
例えば、大学生の履歴書を対象とした Geronimo Web アプリケーションを設計しているとします。このアプリケーションは、個人情報、職歴、そして趣味や関心事など、学生に関するさまざまな情報を保持することになります。このようなデータすべてを入力するフォームを使って学生を提示する場合は、各フォームは短くシンプルにして、主要なテーマを学生の一般情報ページ (名前や連絡先などの情報)、趣味と関心事のページ、アルバイト・ページなど、個別のページに記載するのが賢い方法です。一般に、多数の入力フィールドが連なる長々としたフォームに入力する作業は疎まれるため、入力フィールドの数はできるだけ少なくしてください。
ヒント 2: 乱雑にしないこと。すべてのものを簡潔明瞭にします。
大きなテーマに取り組んでいるときは、1 対多のパターンがあるレコード間の相互関係に注意してください。例えば、一人の学生が複数のアルバイトまたは複数のクラブに関係しているような場合です。このような場合は、学生の連絡先情報を保持するテーブルを、職歴やクラブの活動経歴を保持するテーブルから分ける明らかなサインとなります。(このプロセスは、正式には正規化として知られています。正規化についての詳細は、この記事の終わりにある「参考文献」セクションに記載した関連リンクを参照してください。)
ターゲットを変えない
これらのビューの最終バージョンについてカスタマーの承認を得て、ターゲットの変更に振り回されないようにすることも重要です。Geronimo が生成するフォームとビューの初期設計に十分な時間を費やさないと、後で大きな問題がもちあがります。Geronimo では、フォームおよびビューは一連の JSP ページとして設計できます。これらのページは HTML (Hypertext Markup Language) ページで、システムが処理して表示する値を入力、出力、および計算する Java コードが組み込まれます。
ヒント 3: すべての入力および出力フォームについてカスタマーの承認を得ること。ターゲットが変わることがないようにします。
フィールドについての適切で長いリストを収集したら、システムの概念を定義する次のフェーズ、概念スキーマに進みます。学生の履歴書システムの概念スキーマには、例えばアルバイト、専攻、学校、学生、クラブ、趣味などの抽象概念が組み込まれます。
常に念頭に置かなければならないのは、データベースのビルディング・ブロックとその階層関係です。つまり、データベースはテーブルで構成され、テーブルはフィールドで構成されるということです。スキーマを組み立てる際の最初のフェーズでは、学生とアルバイトなどの主要な概念を用いて入力フォームと出力レポートをおおまかに設計しますが、これが目標とするのはデータベースを構成する最小単位の要素のリストを確立することです。最小単位とはつまり情報のフィールドで、学生 ID、成績平均点 (GPA)、学生の専攻、学校などが含まれます。
後で、これらのフィールドを該当するテーブルにグループ化し、正規化のルールを適用してスキーマを強化することになりますが、とりあえずはテーブルに必要なフィールドのリストを収集してください。
現実から概念へ
広い意味で言うと、コンピューター・プログラマーの仕事は便利な抽象概念を設計することです。すなわち、現実世界に存在するものを見て、コンピューター上でそのシミュレーションを作成するということです。このような抽象概念を Geronimo のクラスとオブジェクトとして表すか、あるいはデータベース・テーブルとして表すかは、主として、抽象概念をどのように使用するか、そしてその抽象概念がどれだけ永続的なものであるかによります。
例えば、年齢は時間の経過とともに変化する値であり、特定の日付 (誕生日または作成日) から計算できるので、データベースでは誕生日または作成日を使用してください。ただし、前述のプロトタイプ・ページのいずれかに Age を表示する場合、その値は年齢の計算対象であるエンティティーを表す Geronimo クラスのメソッドとしてコード内に表すほうが適切です。ここでエンティティーと書いたのは、対象が人間、動物、車であれ、誕生日または作成日は年齢と同じことだからです。
原則として、計算で出された値はデータベースに保管しないでください。その代わりに、その値を算出したパラメーターを保管します。したがって、Age が何らかの出力 (レポートまたは Web ページ) に表示されている場合、これはデータベースから抽出されたのではなく、計算によって出されたものとなります。
ヒント 4: 計算で出せる値はデータベースに保管しないこと。
Geronimo システムには Calendar および Date クラスが定義されているため、日付の計算は難しいことではありません。システムは常に現在の日付と時刻を認識するため、コンピューターにとっては現在の日付から誕生日を引き、年齢の値を取得するのはお手のものです。この原則は、運送時間 (配達日マイナス出荷日)、製品保証の計算 (現在の日付マイナス購入日と保証期間の比較) など、他の日付計算にも適用されます。リスト 1 は、Geronimo による年齢計算の実例です。
リスト 1. 年齢計算を目的とした Geronimo コード
import java.util.Calendar;
import java.util.Date;
public class ddays
{
// Testing Framework.
public static void main(String[] args)
{
// Two date instances.
Calendar date1 = Calendar.getInstance();
Calendar date2 = Calendar.getInstance();
// Set the Birth Date.
date1.set(1975,00,17); // January = 00.
int delta = dDays(date2.getTime(), date1.getTime());
double dyears = (double) delta / 365.25;
System.out.println("Date 1: " + date1.getTime());
System.out.println("Date 2: " + date2.getTime());
System.out.println("Delta: " + delta + " Days");
System.out.println("Age: " + (int) dyears + " Years");
}
// Days between dates.
public static int dDays(Date date1, Date date2)
{
int theDiff = 0;
int totalDiff = 0;
Calendar former = Calendar.getInstance();
Calendar latter = Calendar.getInstance();
if (date1.compareTo(date2) < 0)
{
former.setTime(date1);
latter.setTime(date2);
}
else
{
former.setTime(date2);
latter.setTime(date1);
}
while (former.get(Calendar.YEAR) != latter.get(Calendar.YEAR))
{
theDiff = 365 * (latter.get(Calendar.YEAR) - former.get(Calendar.YEAR));
totalDiff += theDiff;
former.add(Calendar.DAY_OF_YEAR, theDiff);
}
if (former.get(Calendar.DAY_OF_YEAR) != latter.get(Calendar.DAY_OF_YEAR))
{
theDiff = latter.get(Calendar.DAY_OF_YEAR) - former.get(Calendar.DAY_OF_YEAR);
totalDiff += theDiff;
former.add(Calendar.DAY_OF_YEAR, theDiff);
}
return totalDiff;
}
}
|
第 2 フェーズでは、設計対象のテーブル、そしてテーブルに含めるフィールドに焦点を当てます。例えば、基本的な学生情報を持つ学生テーブル、アルバイトに関する学生と時間固有の情報を持つアルバイト・テーブル、そして趣味や関心事などを扱うその他のテーブルが必要になります。プログラム定義を簡潔明瞭にするのが良策であるのと同じく、テーブルも簡潔にしなければなりません。正規化プロセスの一環である情報の要素分析で、情報のすべての最小単位が繰り返されないようにするとともに、あらゆる種類の情報を取得するためのクエリーを明瞭に作成できるようにしなければなりません。
概念の意味を理解する
概念スキーマの次に来るのは論理スキーマ、つまり概念をより詳細に定義し、エンティティーの相互関係を示すデータ・モデルです。第 3 フェーズでは、各種のテーブルに含まれるエンティティーの間に存在するより具体的な関係で概念を変更します。学生 ID がキー・フィールドとして、学生の個人情報をその学生が経験したアルバイト、所属したクラブ、通った学校にリンクします。
概念を理解すると、データベースに適用するクエリーの種類についてもある程度わかるようになります。例えば、大多数の検索がキー・フィールドを基準に行われるか、あるいは多数の検索にキー・フィールドを使わないことが可能かどうかなどといったことです。データベース・エンジンは、指定されたキー・フィールドに基づいてテーブル内に含まれるレコードのインデックスを作成するように設計されています。これらのインデックスは多くの場合、自動的に生成されるため、指定されたキー・フィールドに基づいて検索すると処理速度が大幅に向上します。
ヒント 5: 選択したキー・フィールドは実行するクエリーを実際に反映すること。
そのため、あらゆる概念 (つまり、あらゆるテーブル) で使用するキーが論理的なもので、適用されるクエリーに対して意味を持つことが重要になります。学生が経験したアルバイトについての要約が含まれるアルバイト・テーブルは、会社を検索するためのリストではありません。それぞれのアルバイト・エントリーに学生 ID のキーを付けると、学生の履歴書が動的に作成されるときに、データベースが無駄な作業を最小限に省いて各学生に関連付けられたアルバイトをリストできるようになります。
コンピューターがキー・フィールドを使用しないでレコードのリストを作成すると、その処理速度が大幅に落ちる可能性があります。アルバイト・テーブルは学生が経験したアルバイトのリストをコンパイルするためのものなので、このテーブルをその他の目的で使用すると非効率的です。
正規化
データベースの正規化という重要な話題については大々的な記事を書くことが可能で、現に多くの記事も書かれています。正規化は、データの冗長性を排除してデータを効率的に編成します。正規化のプロセスには、すべてのデータベース属性がそれぞれ 1 つの値だけを格納すること、そして複数の値を持つ属性が異なるテーブル内にあることを確実にするという目的があります。例えば、以下の学生レコードを見てください。
Student: John Smith, College GPA: 3.20
学生と GPA の間には 1 対 1 の関係が存在します。この関係は 1NF、または第 1 正規形と呼ばれることもあり、正規化のルールに従っています。これが最終的な目標で、すべての学生には大学 GPA が 1 つだけ関連付けられるようにします。
ただし、この学生は学生時代に複数の異なるアルバイトを経験しています。その結果、彼の学生レコードは以下のようになります。
Student: John Smith, Job: Smith Brothers, Campus Coffee Shop, Bob's Burgers
Job という 1 つの属性に複数の値がありますが、正規化のルールに従うと、これらの値は別のテーブル (アルバイト・テーブル) に移さなければなりません。その上でアルバイト・テーブルに学生 ID でインデックスを付け、経験したあらゆるアルバイトの検索を規則正しく効率的に完了できるようにします。
ヒント 6: 正規化のルールは重要です。ルールを把握し、適用してください。
正規化のすべてのルールを記載したり、正規化ルールの基礎となっている数学的背景を説明するのは、この記事の対象外です。ただし、データベース・システムを作成するには、正規化の概念を十分理解しなければならないとだけ言っておきます。(正規化に関する優れた記事へのリンクは、「参考文献」に記載されています。)
まとめ
オブジェクト指向システムの設計には数多くのツールを利用できるように、優れたデータベース・スキーマを作成する際にも利用できるツールがたくさんあります。これらのツールと手法を調べ、実践を通じて技量を磨くのに時間を割く価値はあります。現代のビジネスはデータベースと Webサイトで行われますが、Geronimo はこの 2 つを統合する強力なツールです。
参考文献 学ぶために
製品や技術を入手するために
議論するために
著者について  | 
|  | Bill Zimmerly は知識エンジニア、各種バージョンの UNIX® および Microsoft® Windows® ソフトウェアの専門知識を持つ下位システムのプログラマー、そしてロジックの崇拝者でもあり、新しい技術を生み出し、その技術についての記事を書くことに熱意を燃やしています。Bill は、新鮮な空気と素晴らしい景色に溢れ、そして優れたワイナリーが点在するミズーリ州ヒルズボロに住んでいます。 |
記事の評価
|