[DBデザイン#10] 実例から考える: データベースの理論は勉強する必要があるか?

ちょっと、閑話休題的な話にしましょう。データベースの教科書では、集合論の話から入るいわば数学的な議論を土台にした解説が進められます。しかしながら、実際にデータベースを使い、設計をする上で、そのデータベースの教科書に書かれていることと、実用的なノウハウとの間に隔たりが大きいことに気付く人も多いでしょう。隔たりというか、世界が違い過ぎるというイメージを持つと思います。また、第3正規形などの考え方を学ぶのですが、それらの知識だけでは設計をこなすには遠いと思う人も多いようです。データベースの理論や数学は不要なのでしょうか? もちろん、不要とは言い切れないのですが、その辺り考えていることをまとめてみましょう。

まず、数学をベースにした理論は、初心者向けの情報ではないことは確かです。データベースの理論が数学をベースに組み立てられていることで、さまざまなことが高度に客観的に検証したり、証明したりということができるのです。つまり、数学がベースにあることで、確固した結論が得られていると考えられるというところがポイントです。よって、数学ベースの理論は無視はできないのです。厳密すぎて、最初の定義、つまり集合やドメインという話からリレーションの成り立ちまでの話はいきなり理解ができません。それはいきなりは理解できないのは当然だと思います。抽象度が高過ぎです。今時はデータベースシステムを手軽に組んで利用できる世界なので、むしろ、現実のデータをいじりながら理解し、一定のところまで理解したところで理論を勉強するというのが効率的な方法ではないかと思います。実際、私も、理論の書籍を最初に読んだ時には面食らいましたが、実際にいろんな製品を触って作ったりしている上で改めて理論の書籍を読むと、非常に頭に素直に入ってきたという経験があります。

データベースの設計におけるノウハウは、実はこうした理論に裏打ちされていると言ってもいいのですが、理論の世界で定義されていることは抽象度が高いために、打てば響く的なノウハウではないのは確かです。常に抽象度の高い世界で過ごすのは、さすがに専門家でも辛いですし、実システムは利用者あるいは発注者という存在がいるので、現実の世界に沿った説明をする必要も出てきます。その上で、いろいろな理解しやすくアレンジされたナレッジを多くの人は発案し、あるいは獲得するということをおこなってきたわけです。

そうしたナレッジが、理論の世界のどれと対応しているのかというのは、ある意味面白い話題です。表を分離するというのは第1正規形を適用しているとも言えます。しかし、直接関係してなさそうだけど、重要なナレッジもあると思うかもしれません。いずれ説明しますが、多対多の関係は中間テーブルを確保するという有名なノウハウがありますが、これは実際にそういう実装をせざるを得ないという工夫のノウハウでもあります。ただ、この手法自体は結果的に第3正規形になっているとも言えるわけで、要するに理論上での重要な結論は、必ずしも設計のナレッジのコアであるとは限らないのです。ただ、第4、第5正規形となると、これはちょっと狭い範囲の解決策ではないかとも思います。どんなデータベースでも、第5正規形の領域まで到達するということではありません。ただ、通常は第3正規形までは間違いなく到達していないと、どこかで矛盾が生じると思います。一方、マスターのデータをコピーして残しておくような処理、例えばFileMakerでのルックアップのような処理は、正規形による効率化とは逆行する面もあるものの、要求を満たすという意味で1つの選択肢になります。ただ、これも、逆に正規化が崩れている側面をどう評価するということを考えれば、やはり理論に基づいて考えを及ばせることができるとも言えるのではないでしょうか。この辺り、先々のネタで使います。

そういうわけで、私の一連のブログ記事は、プロの開発者でも、データベース設計となるとちょっと分からんという人や、あるいはそれなりに作れても自己流というか、持ち前の能力でうまくやってきたのが果たして正しい考え方なのかといった疑問を持っているような人に、設計時に何を考えればいいのかということを、理論とは異なる流れで説明をする試なのです。

ちなみに、理論や数学は学習する必要があるでしょうか? 真面目に設計をできるようになりたい方は、必ず勉強してください。よく分からなくても、ともかく頭に一度理論を流してください。忘れてもいいので、ともかく一度は勉強しましょう。そうすれば、ずっと先に、「あ、これはあのことか」というのがたまーに出てきます。それが基礎力というものではないかと思います。ただ、数学は若いうちに学習しましょう。中年以上になると、無理〜!と叫ぶことになります。私と同世代の老化著しい皆さんは、時間をかけて、そして欲張らずに勉強するしかないかと思います。

[DBデザイン#9] 実例から考える: 分離した表から元の表を得る

ここまでのところで、業務分析して、各部署で必要なデータがどんなものかを見える化するために、表を作りました。表の1行1行が表現している内容を考えれば、同じ商品という単語を使っていても、部署ごとに扱い、つまりは商品に対する概念や定義が違っていることに気づきました。また、一方、共通の概念もあり、それは商品の名前は共通であるということで、商品マスターに名前を覚えさせておこうという判断ができたわけです。

この時、商品の表を、製造管理の表の「商品名」フィールドをごっそり持ってくるということでいいのですが、同一名称の行が発生します。今のところ、商品名だけしか商品の表では登場していないので、重複したデータはなくてもいいだろうと考えます。1つだけ記憶していれば問題はないと考えます。製造管理の表では複数の同一商品が存在しますが、それぞれが同一の商品の行を参照すれば、問題はないわけです。ということで、商品の表は商品名の重複がないものにして、番号を振ったということです。

こうして分離しても、元の製造管理の表が得られます。その手続きは次の表の通りです。少ないデータだけならこうして具体的にデータを並べて考えてみるのがわかりやすいでしょう。

最初は分離した表になっていますが、左側の製造管理について、最初の1行を取り出します。すると、商品の102番を参照するようになっているので、商品の表の102番の行を照合し、そしてそれぞれ取り出します。続いて、この2つの1行を、1行にまとめます。つまり、単につなげます。この作業を、左側の製造管理の各行について行うと、最後の表になります。これは、商品の表を分離する前の製造管理の表と基本的に同じです。フィールドの順序は違いますし、商品IDも入っていますが、表として表現していることは同等であると言えるはずです。つまり、どちらの表でも、業務は同様に可能です。

このような、表から表を作る処理を「結合」と呼びます。リレーショナルデータベースの代表的な処理です。SQLでは、JOINというキーワードでステートメント内で記述します。ただ、JOINの処理にもいくつか種類がありますが、これはまた別の機会に説明しましょう。

ここで注目していただきたいのは、商品の表は重複を削除していても、問題なく元の表が再現できるということです。「ロボットいか2号」という文字列を、図で見たように、1つ目と2つ目のレコードで使いまわしています。言い換えれば共有しているのです。どちらも『行を取り出す』と記載する部分で、いわば元の行の複製を作っていて、それを結合した表に持ち込んでいます。結合した表の商品名は、全て、商品の表から複製した情報であるため、当たり前ですが、商品テーブルのデータが正確に結合した表に組み込まれていて、同一の商品の商品名は常に同一であるということです。

この結合結果は、基本的には一時的に使うのものであって、この結合した表自体を永続的に記録しているわけではありません。永続的に記録されているのは、ここでは手続きの最初の2つの表であるのが、データベースの一般的な実装になります。ただし、データ処理を高速化するために結合結果をどこかに覚えておくような最適化処理は今時のデータベースは普通になされていると言ってもよく、厳密に技術的な意味では永続化されているかもしれません。しかしながら、設計の段階では、必要に応じて結合した表を一時的に、つまり、現状の情報を一覧表を作って参照すると言ったような用途で作るという流れが一般的であると考えてください。

次回は、販売明細について検討を進めてみましょう。

[DBデザイン#8] 実例から考える: 分離した表の関係を築く

ここまでに、業務全体をみながら、同じ「商品」でも部署ごとに異なる対象として扱っていることから、記録したいデータは異なるとして、それらを表として表現しました。一方、その中でも共通の「商品」に対する情報を別の表でまとめて共有することも考えました。

この、別の表にしたもの、つまり、複数の表にしたものを1つの表として表現するということが、リレーショナルデータベースのわかりやすいメリットの1つです。なお、この1つにまとめた表は、場合によってはどこかに保存することもあるかもしれませんが、原則として一時的に利用するものであって、それを保存するデータとして利用はしません。あくまで、複数の表として保存し、必要な時にそこから元の表を一時的に得るというのが原則です。

しかし、表を分割したとしても、その2つの表の関連性はどのように確保するのでしょうか? ここで、本来はデータベースの難しい理論を勉強しなければならないのですが、1つの理解の仕方は、参照される側に「番号を降る」ということをやるのです。次の図は、「製造管理」の表に、もともと商品名があったのですが、その商品の名前は営業部門などと共有できそうなので、「商品」という表を分離しました。しかし、分離してしまったらただ消すだけです。製造管理の1行において、どの商品についての製造管理情報なのかを示すために、ここでは「商品ID」という番号を振ることにします。ここでは、「商品」側にも「商品ID」があります。商品IDは、商品が重複しない表の上で、適当な番号を頭から振っていったものです。当然ながら、商品の表の商品IDは重複がありません。言い換えれば、商品IDが決まれば、「どの商品なのか」ということが一意に決まるということです。こうすれば、製造管理の1行目は商品IDが102なので、商品の表より「ロボットいか2号」についての情報であるということがわかるのです。もちろん、ソフトウェアなのでこれをある意味機械的に行うのですが、ここでは設計に必要な概念を整理するために、まずは番号を振るということを考えます。ちなみに、番号を101から順番に振りましたが、別に1、2、3でも、10001からでも構いません。とにかく行ごとに異なる番号であればいいのです。一桁だと、個数っぽいので、わざと桁を多めにして、直感的に判断しやすいようにという意図です。

(「本セミナー」と書いてあるのは、もともとセミナー用に作った資料を流用しているからです。すみませんが無視してください。なお、いずれ、正規形についての情報は色々な形で紹介すると思います。)

ここで、製造管理は5行、商品は3行です。「ロボットいか2号」についての情報が製造管理には2つあり、つまり、2個の商品の製造をしたことがわかります。一方で、商品の表については、ここでは名前の共有だけを目指しているようなのですが、2個製造した「ロボットいか2号」は、どちらも同一の「ロボットいか2号」という商品名です。ということは、商品側では1つの存在で良いと言えます。

商品から逆に製造管理を見たとき、1つの商品「ロボットいか2号」についての情報が1行目と2行目の複数の行にあります。このような関係を「1対多」と呼ばれます。この製造管理の表はおそらく全体の表の一部なので、2個しか製造していないということはないでしょう。つまり、100個あるいは10000個と作っているような状況を想定します。具体的なデータでは何個という個数は求められますが、設計については、具体的な個数よりも「多」であって「1」や「0」といった決まった数値ではないということが重要になります。もちろん、0、1、2・・・と増えていくということで、1である瞬間はあるのかもしれませんが、「関係そのものについて、1なのか多なのか」ということを考えます。となると、商品と製造管理は、1対多であると言えるわけです。

1対多の「1」は、1行しかないということではありません。商品の1つから多数の製造管理が存在し得るということです。そして、逆に見た時には、1つの製造管理から、1つの商品が特定できるということです。このような関係を1対多と呼んでいます。逆に見た時は1対1じゃないかと思うかもしれませんが、一方が1対多なら、関係は1対多と判断します。ちなみに、「多対1」も基本的には同一概念です。説明上の順番で、「商品と製品管理は1対多」、「製品管理と商品は多対1」のような表現がされるだけで、どっちが先に書いてあるのかくらいの違いしかありません。

現実のデータベース設計ではこの「1対多」の関係を、確実に抽出しなければなりません。これに対して、前回説明した「1対1」の関係もあります。1対1の関係は、多くの場合はフィールド、つまり表の列にまとめることができます。一方、1対多の関係は、別々の表として表現するというのが確実な方法になります。本来1対多であるはずの関係を間違えて1対1であるとみなしてしまったら、単純な意味では2つ以上のデータの存在をシステム上では適切に表現できないということになります。すなわち、1対多の関係の把握が、データベース設計での肝になるということになります。

なお、以前にもよく雑誌記事などを書いたときに、リレーショナルデータベースの説明を依頼されたことがあります。そこで必ず言われるのが「番号が分かりにくい。番号が出てきたらもわからない」という編集者からの指摘です。まあ、そうですね。なんで101なのとか(前に説明した通りこれは適当な番号です)、データベースは直感的と言われるのだからもっと簡単なのじゃないかとか言われるのですが、この「番号振ります」は、単なる手続きなので、難しいことではありません。普段から番号を振って、順序を考える基準にするなどしていることと同じことなのです。ただ、普段番号を振らない、あるいは元々番号を使っていない対象に単に振っているだけです。番号振ること自体をディープに理解してほしいわけではなく、ここである意味、表に分割した結果を単純化するために番号を振るという状況を頭の中で作ってほしいというだけで、考えすぎる必要はないと思います。繰り返しますが、番号を振るのは単なる手続きです。

一方、この「ID番号」は、リレーショナルデータベースの理論の上からは必須の定義ではありません。リレーショナルデータベースは、その表の1行を特定できるデータが何かということが重視されるので、それは商品名でもいいですし、社内で使っている商品番号でもいいのです。むしろ、論理的にはその方が現実に近いということもあります。こうした表の1行を特定可能なデータを「キー」などと呼ばれます。ただ、これまでの色々な設計の経験からして、全ての表に連番を振っておくのがある意味確実だと考えます。まず、データベースは連番を振ることを自動的にできるからです。場合によってはその連番を使わないこともありますが、それによって処理が遅くなったり、ディスク容量を圧迫するようなことはないのが一般的なので、「全ての表にキーが絶対に存在する」ことを優先して、数値連番フィールドを設定します。商品名がキーでもいいじゃないかと思われるかもしれませんが、文字列は比較処理がある意味安定していません。整数やUUIDのような一定のコードは比較処理が安定しています。文字列の場合、もちろんルールを定めれば、確実に比較はできますが、Unicodeのさまざまルールや、同じ文字でもコードが違うものが大量にあるなど、文字列比較は間違える要因が多いのです。であれば、整数連番の確実性を取りたいと考えるわけです。付けられた連番がデータと無関係にランダムになるのを嫌う場合もありますが、このキーになるデータは「利用者に見せない」のが基本です。仮に見せたとしても絶対に編集可能にしてはいけません。最近は多くの開発にフレームワークを使うこともあるので、自動的に数値連番をつけることもありますし、単一の数値での処理が組み込まれていることもあるので、結果的に数値連番フィールドを使うことになるのではないでしょうか。

次回は、この分離した表から元の表が求められるということを、細かい流れになりますが、説明しましょう。

[DBデザイン#7] 実例から考える: 共通の概念を抽出する

前回の再掲になりますが、ここまでに、部署ごとに、その部署での関心ごとについて表にしていきました。ここで、フィールド名をつけるところまでを解説しました。

続いて、この一連の表から、共通の概念を持つデータを抽出します。厳密には、正規化の議論があって、そのルールに基づくという手法もあるのですが、ここでは会社のドメイン、部署のドメインについて、要求分析を通じてだいぶんと理解が深まったという状況をもとに考えてみましょう。

まず、ここでどの表にも「商品名」があります。であれば、商品名を共通化することで何かメリットは生まれないかと言うことを考えます。それぞれの表にも名前をつけることにしますが、加えて、商品名だけを独立させた「商品」と言う表も記述してみました。つまり、「販売明細」「製造管理」「カタログ在庫」いずれも、「商品」にある商品名の文字列を持ってきて表が作れるというものです。こうすれば、販売管理や製造管理において、何度も繰り返し登場する1つの商品名を記述することなく、商品名はシステムの中では商品の中に1箇所登場するだけにすることもできそうです。効率が良くなるかもしれません。

ちなみに、これが「商品マスター」と呼ばれる考え方の1つの理解の仕方です。効率良いことと、修正の確実性ということが言われます。例えば、商品名を間違って記録していたら、それが最初の図のような表の場合、表の中で一括置換をするなど、変更が重い処理になり、また確実に終わりそうにない処理にもなります。マスターで一元的に商品名を管理すると、商品名が違っていても、1箇所直すだけです。しかしながら、商品名の間違いってそんな頻繁にはないでしょうという気もするかもしれません。実際そうですが、実はマスターの役割は確実に変更できるということ以外にさまざまなことがあります。システム内では、データの複製をするような場合が出てきます。要求から、ここのフィールドは複製が必要と判断される箇所は時々出てきます。その場合でも、マスターの内容を複製することで、確実に名前を入力できると言ったこともあります。この辺りは、リレーショナルデータベースの理屈だけでは説明しきれない側面です。ただ、実際にある製造管理によって管理されている個体の商品が、商品テーブルをどのように参照するのかということは、実装上のルールがあって、それは次回に説明したいと思います。

「商品」という存在は、部署によって共通であり、商品名は、どの部署でも同様に利用できるという、ここでは表にまたがって存在するデータの共通性を見つけました。実際には、さらに販売先顧客名が重複しているなどの問題はありますが、それは追々見つけましょう。

ここで、概念が共通という意味では、日付もそうではないかと思いませんか? もちろん、販売日と製造日は、対象が異なりますが、いずれも、日付という共通の概念ではないかと思うところです。たまたま、この表では同じ日がなかったということです。では、日付を共通化するのかというと、おそらく多くのデータベースでは共通化していないと思われます。これはなぜなのでしょうか? 日付や時刻はいずれも3つの整数を持つような複合データであり、突き詰めて考えれば複雑そうです。この結論を先に言えば、日付や日付時刻といったデータは、データベースが持つ型として定義されているからです。言い訳っぽい理由になりますが、「商品」という型はありませんが、DATEやTIMESTAMPといった型があり、日付という単独の値、つまり、数値などと同じように扱えるから、多くの場合は別の表に分離しないということです。仮に別の表に分離しても、1フィールドだけです。商品の場合は、ここでは明示していませんが、おそらく商品名だけでなく、販売開始日など、共通の概念として「商品」に紐づく属性がフィールドとして付加されることになるでしょう。つまり、この会社における共通概念の商品を扱うために必要な情報を追加することになります。しかしながら、日付は多分日付だけなのだろうと思われます。

しかし、日付を別の表に分離しないと対処しづらい場合もあります。それは日付以外の情報が入っている場合で、例えば、祝日の管理が挙げられます。また、その会社特有の記念日(創立記念日など)もあります。そうなると、日付にもう少し意味が付加されてしまい、実はそれは「予定表」だったりして、「日付」という概念ではなくなってくるでしょう。予定表の日付ということで、ここでも日付という型があることで、単独フィールドとして扱えるというあたりが日付時刻についての特殊性とも言えます。

このように、とにかく「マスターを作る」というデータは1つの案件内では結構あり、いくらか経験を積めば、大体いい感じに設計できると思います。しかしながら、そこには、表ごとに異なる「商品」と、表を通じて共通の「商品」の概念があって、後者がマスターになるということを理解しておく必要があります。ところで、共通というのは実は抽出時に考えることで、運用上はそこまで厳しくありません。商品の販売単価は、おそらくはここでは営業部門だけが使いたいでしょう。では、それは商品マスターに入れるのかというと、実は入れることが一般的です。これは、他の部門では無視すればいいというのがまずはざっくりとした見方なのですが、より重要な概念があります。単価は、その共通概念である商品1つについて、1つの値が割り当てられる属性であるとみなすことができれば、それは商品マスターのフィールドの一つにすればいいのです。そして、必要な表では使い、不要な表では無視するというのがデータベース利用のポイントになります。ここで、「商品1つについて1つの属性」、つまり、1対1の関係であることをしっかりと考え、確認しておく必要があります。実は、部門午後の表のフィールドは、その表1行の概念に対して、1対1の関係が成り立っているものが並んでいます。作ってある表はちょっと恣意的ではありますが、こうすれば、整理されているとも言えるでしょう。

次回は、分離した表から必要な情報を持ってくるというリレーショナルデータベースの基本的な考え方を説明しましょう。

[DBデザイン#6] 実例から考える: 表で考える

前回までに、単純な「商品」という単語でも、状況によって異なるものを示すことを説明しました。実際の開発では、これと同じように、たくさんのユビキタス言語を認識して、それらを分析し、必要な仕組みを考えていくことになります。その時に有用な考え方が、まさに「表」です。それぞれの部署で記録したいデータを実際に表に作ってみます。場合によってはすでにその部署で表が作られている可能性もあります。しかしながら、もっと大雑把なデータしか得られないかもしれません。これは利用者側作るものではあるのですが、表の内容が無茶苦茶でないかなどはやはりエンジニアリング的な視点でチェックしないといけません。表の内容が途中から変わってしまっているような表の利用は要注意です。

それで、ここでの実例でできたおもちゃロボットメーカーについて、ちょっと恣意的ですが、システム化したい業務についての根幹となるデータを表にしてみます。現実にはこんなに単純明快ではないとは思いますが、考え方のサンプルということです。

現状、多くの仕事はExcelが絡んでくるので、中途半端にシステム化されていることが多いでしょう。特にExcel自体を「便利に使っている」ような職場では、システム化と言っても、ヘタをするとExcelの再発明を求められてしまうことも、結構あります。表にするのですが、ここで何を求めたいかのかというと、1レコードに相当するものとして何を見るのかということです。実は営業部門が一番わかりにくいです。営業については実際にはリレーショナルデータベースの典型的な例でもあるので、少し先に詳しく説明しますが、あえて「営業は、紙の納品書を作っている」くらいの感じで考えていただければ、いつ、どの顧客に、どの商品をいくつ売ったのかという情報を記録することで、月末にまとめて請求ということができるかと考えます。ここでの表は、納品書の明細が1レコードになりそうです。言い換えれば、それより小さな単位がなさそうであるというくらいの根拠です。商品や顧客は当然ながら表には繰り返し登場します。

製造部門はある意味わかりやすいです。作った箱入り製品1つずつを管理したいのですから、1レコードは、1ボックスということになります。マーケティング部門は、とりあえず製品カタログの残り部数を管理するとしたら、1レコードは、まさにマーケティング部門が把握する1商品ということになります。

なお、このままだと、データベースの設計に持ち込めません、ここからまだやるべきことはあるのですが、重要なことは、実際に現場で発生しているデータを記述するということです。ここで、単に曖昧に記述するのではなく、表の形で頑張って記述するということです。全部でなくても構いませんが、少なくとも、表の数行分を記述してみることが必要と考えます。もっとも、そういう表の形になったものを頭の中で再現して、何も書かずにできる人もいます。設計が得意な方はそれができるかもしれません。しかしながら、こうして作り込んで行くコアな考え方が正しいかどうかを検証するのは設計が不得意な人かもしれません。記述して見える化するという意味では、表は出発点としてはみんなが理解できるものとも言えるもので、大変有益でしょう。

ちなみに、ここではそれなりに整理してしまっている感じですが、空白があるのは当然としても、同じ列に途中からデータの種類が変わってしまうこともあります。その場合は列を分けるなどします。つまり、列で分類するという言い方もできるでしょう。そうしているうちに、列に名称をつけることができるようになります。その列にあるデータの代表的な名前をつければ、逆にその列に何のデータが入れられるのかも理解しやすくなります。もちろん、それがすでに紹介したフィールド名になります。

フィールド名の命名ルールは結構人それぞれですが、少なくとも、「代表名」であるというのはほぼ全ての方に同意いただけるでしょう。また、データベース上では同一のフィールド名を複数つけることは許されていませんので、異なるフィールド名にしなければなりません。また、長すぎると式を書いたりするような時に結構面倒です。ということで色々悩みます。以前に大変分析が困難なデータベースにあたったのですが、どう困難かというと色々あるのですけど、「適用_編集用」と「適用編集用」みたいなフィールドがあって、フィールド名で判断が極めて困難という状況でした。このようなフィールド名だと、「フィールド1」「フィールド2」と付けられているのとあまり変わりません。さらにその時にはオチがあって、それらのフィールドの前者はPDF出力時、後者は印刷時に使われるというこれまたクイズのような(パズルではなく!)データベースでした。

いずれにしても、フィールド名はよく考えて、統一的な名前で、かつそこに入ってくるデータが連想しやすいものにするのが言うまでもありません。例えば、「平均値」と言う名前のフィールドをつけたけど、そこには月間の平均値が入っているとします。しかし、やっぱり週の平均値も欲しいので「平均値_週間」フィールドを作ったとします。そうなると、「平均値」ではなく、「平均値_月間」フィールドにするのがベターな方法ではあるのですが、そこをそのままにするエンジニアが多く、後からデータベースに関わる人たちに混乱をもたらしてくれます。もちろん、プログラム内にフィールド名が文字列で記述するような場合、下手にフィールド名は変えたくないと思うかもしれませんが、一括置換すればいいことです。また、FileMakerでは基本的に気軽にフィールド名は後から変えられます。今、この平均値が売上だったとして、個数の平均値が欲しいとなると、どうしましょう。この集計した結果のフィールドは「売上_平均_月間」のように、処理対象、処理方法、グループ化基準といった情報が、どのフィールドにも、同一のルールで、同一の用語で入っていないと、分析が辛くなります。日本語の用語だと思っていたら、途中から突然英語になってしかもカタカナだと(「売上_アベレージ_年間」みたいな)何かのギャグか嫌がらせかと思ってしまします。用語のルールも重要ですが、自分で決めたルールを全体にわたって最後まで踏襲するということがもっと重要なことになります。

ところで、フィールド名自体に「データ」的な性質の文字列が入るのは、ちょっと違和感あるものの、ある意味便利なのかもしれません。例えば、アマゾンから購入したかどうかを記録する「Amazon購入」フィールドはどうでしょう? では楽天やモノタロウと購入先を増えてきた時にそれぞれ別々に管理したければ、フィールドを増やすしかありません。通常、そうなると、「購入先」と言うフィールドに文字や数字で区別して購入先を記録するのが妥当な気がします。となると、フィールド名は抽象度の上がった名称であるとも言えて、実はフィールド名にデータ(この場合は「Amazon」と言う文字列がある意味ではデータです)が入ることはないと言うことも言えます。しかし、単にAmazonだけ特別で管理したい場合には、「Amazon購入」フィールドは、わかりやすいので悪くはないと思います。この問題は、結果的に最後まで作ってみないと正しかったのか、正しくなかったのかはわからないものの、ルール的には一概に決められないと言うことでもあります。

そういえば、フィールド名に表の名前を入れるかどうか問題もあります。これに関しては入れないのが基本だと思います。入れるとしたら、全部のフィールドに入れないと妙にも思えるからで、それは非効率的です。ところが、「名前」と言うフィールド名は、それだけ単独あってもわかりづらいです。そのような場合は「商品_名前」にするという手もありますが、SQLの世界では「テーブル名.フィールド名」の記述が随所にできるので、表の名前はフィールドになくても、表現は可能とも言えます。ですが、極めて一般的な名称については、やっぱり表の名前をつけたり、あるいはそれを連想させる名前をつけたくなってしまいたくなります。これは感覚的な問題です。加えて、あちこちのテーブルに「名前」フィールドがあるのも、混乱の元かもしれません。

ついでに、フィールド名に誤変換や間違えたスペルはなるべくやめましょう。データベースを分析しているときにストレスが強くかかります。見る度に、何だか設計・分析とは違うスイッチが入るのですよ。スペルは今時の開発ツールではみてくれますが、誤変換は自分で見つけるしかありません。データベース全体に渡って「精算」であるはずが「清算」だったものを見たことがあります。レイアウト上は流石に利用者が指摘したのか「精算」になっているのですが、フィールド名が全部「清算」でした。

次回は、この表にした結果をもう少し分析してみましょう。

[DBデザイン#5] 実例から考える: “商品”に注目する

前の記事では前提となる会社の業務を紹介しましたが、どの部署にも「商品」という単語が出てきました。データベースに慣れているみなさんは「はいはい、『商品マスター』でしょ」と思われるところかもしれません。もちろん、商品マスターは作るのですが、なぜ商品マスターが必要なのでしょうか、そして、それだけでいいのでしょうか?ここで、「商品」というキーワードをより詳細に分析してみます。

次の図では、それぞれの部門に対して、「商品とはなんでしょうか?」と質問した結果だと考えてください。実際、要求分析をするときに、そんなダイレクトな質問はいろんな意味で(機会やあるいは適切な担当者と話ができるのかなどを含めて)無理でしょうし、しかもちゃんと答えてくれるとも限りません。通常は、いろんなインタビューをもとに、分析者がこうではないだろうかと考えるのが一般的かと思います。なお、前回は経営者が出てきましたが、言っていることが曖昧なので、ここから先は3部門だけに絞りましょう。

営業部門にとって、商品は売っているものです。製造部門は作っているものです。この辺りは明確でしょうけど、どうもマーケティング部門にとっては、商品というのは何なのかということがどうも曖昧で、具体的に言いづらい感じです。おそらく、状況によって変わるのでしょう。

ここで、部署ごとに、商品をどのように扱っているのかをみてみましょう。それを示したのが次の図です。

まず、製造部門は、製造した商品1つ1つをどうやら管理したいようです。つまり、商品の箱1つ1つが対象になります。一方、営業部門は、商品の箱があることは理解しているでしょうけど、商品そのものを集合的に扱います。しかも、製造部門は、商品の物理的なことを考えなければなりませんので、在庫ということまでもしかして考えているかもしれませんが、営業部門はおそらく商品という存在を移動させているという考えが支配的ではないでしょうか。つまり、営業担当者は、実際に自分で箱を手に取って顧客に届けているというよりも、伝票を書いて、ロジスティックスに依頼をするわけで、実際に商品そのものを目に見ていることは滅多にないようなのがいわゆる営業という活動ではないかと思われます。マーケティングに至ってはなんだかわかりませんが、インタビューでどうやら商品カタログの管理くらいは必要なことがわかったという程度です。

同じ商品という呼び方をしているのに、このように部署によって実は扱う概念が大きく変わってきます。当然、それらを一緒くたにするのは問題があると考えます。部署ごとに違いがある一方、共通の概念もあります。例えば、商品名は社内で統一的に扱われているはずです。一方、商品の単価が業務上必要でしょうか? 販売部門は伝票を作成するのに必要そうです。一方、製造部門は単価が存在しても、業務上は通常は使わないでしょう。一方、マーケティングはおそらく単価情報は、業績等をチェックするような場合に使うかもしれません。商品1つずつにつけるシリアル番号はどうでしょう? 製造部門には必須かもしれませんが、営業部門には興味のないデータです。このように、共通のものと共通でないものが存在するのです。

ドメイン駆動開発の世界では、こうした概念を「ユビキタス言語」として捉えます。ある特定のコミュニティで通用する言語なのですが、つまり、ここでは「営業部門言語の商品」と「製造部門言語の商品」に若干の違いがあると考えて、これらの部門間では異なるユビキタス言語が使われていると考えます。同じ言葉で違う概念があるということは、ドメインつまり「業務そのものの定義」が異なるという考え方です。実は、商品というよく似た言葉でも、このような違いがあるものの、社内で働いていると、なんとなくそういうものだということでドメインが違うことは気づきにくいものです。まさに、第三者が設計するときに、そうしたドメインの違いを見出すことができ、業務の整理が進むということが期待できます。もちろん、分析者や開発者は、顧客のドメインを理解し、ユビキタス言語を使いこなせるくらいになっていることが理想です。

ユビキタス言語は、そのドメインのモデルの基礎になるものです。言語を構成する概念を整理したものがモデルとして利用できるでしょう。ユビキタス言語はモデルが表面に出てきたものでもあります。私たちは、ドメインのモデルを知りたいのです。そのモデルをデータベースに実装すれば、システムは成功するはずです。モデルを探るのが要求分析であり設計です。その手がかりがユビキタス言語にもあるということです。

ちなみに、1つの言葉が異なる概念を示すだけでなく、異なる言葉が同じものを指す場合もありますし、1つの単語が状況によって異なるものを示す場合もあります。最後の例は1つの単語が同一職場の同一業務で状況によって違っていたのですが、よくそれでトラブル発生しないもんだと思ってしまいます。たまたま問題にならなかったのでしょう。言葉というのはコンテキストを引き連れて登場するので、区別は可能なのかもしれませんが、外部からその世界に入ってきた人には面食らってしまう事象です。こういう事例があった場合は、ドメインをまたがって用語の整理をするのが理想なのですが、なかなか業務の上で使い続けている言葉は変えてもらえないのが実情です。

ドメイン駆動開発といえば、現在はマイクロサービシズで話題になっていますが、ドメイン駆動開発の方が先に提唱されていた概念です。マイクロサービシズでは、どんなサービスに分割をするのかというのが設計上の大きな問題です。ここでサービスの分割を考えるとき、ユビキタス言語の通用する範囲を重視するという考え方があります。これを、非常に雑に考えると、要するに部署ごとに別システムであり、部署間の動きが必要ならそれはシステム連携だろう、そしてシステムは1つのマイクロサービスであるとも言えるとも言えます。実は、マイクロサービスシズの勉強を一時期頑張っていた時期があり、いろんな資料に当たったのですが、あっさりと「マイクロサービシズは、部署ごとに分ます、以上」と説明されているものがありました。その資料ではドメイン駆動開発やユビキタス言語といった抽象概念はすっ飛ばしていました。あらあらと思いつつ、非常に大まかに言えばそういうことで、間違いはないかもしれませんが、会社の部門構成が最適化されていないと色々苦しいだろうなと思ったりもします。しかし、最適化されていない会社ってきっと破綻するでしょうから、システム作っても早晩使われなくなる? ということで、部署でサービス分けるというのはあながち悪いサジェスチョンではないと思った次第です。そこで、ここでの実例も、部署を単位にしてみました。

商品のような基本的な単語でも、そのドメインによって役割が違うようです。実際、みなさんの会社やあるいは扱った案件ではどうでしょう? 他には「在庫」なんてどうでしょう。在庫と言ってもいろんな概念があります。会計的には在庫は金額ですが、倉庫で働く人にとってはそこにあるたくさんの段ボールだったりします。商品や在庫などはどの会社でもあるようなものなので、ある意味では扱い方はある程度はわかっているようなものでもあり、経験則も適用できるかもしれませんが、むしろ、わかったつもりになるのは危険で、そのドメイン特有のルールや扱い方がないかを常にアンテナを張るくらいの気持ちがないと、後から気づいて大きく出戻りが発生するということにもなりかねません。商品や在庫だけでなく、部署ごとに違う、あるいは担当者ごとに違うような概念がないかを見つけてみるのも良いでしょう。また、部署で違うだけでなく、部署を横断するようなドメインの存在も見えてくるかもしれません。要求分析以降は常にドメインやそこでのモデルを意識する必要があります。

次回は、異なる概念を表を作って捉えるということを説明しましょう。

[DBデザイン#4] 実例から考える: 前提となる業務

今回から、数回に分けて、データベース設計をするときにどこに注目するのかを考えることにします。一応、「分かりやすい」業務を架空の会社でおこなっているという想定です。もっとも、そういう架空の設定そのものが、いかにも記事をそれらしく見せるためのわざとらしい前提に見えるかもしれませんが、やはり現実の世界そのままはなかなか複雑で理解しづらいですし、現実には「要求が不明あるいは曖昧である」という問題との対峙が非常に難しいところになります。なので、問題を単純化したいと思います。

データベース設計の1つの肝は、「1レコードに相当する単位あるいは概念の特定」だと考えます。そのために、どんなフィールドが必要かを集めて分類などを行うと思いますが、1レコードの特定が設計の1つの目標になります。そこに至るまでに、表にして考えるということをまずはこの実例で見ていっていただきたいのですが、表が出てくるのは次回以降になります。まずは、ロボット製造販売を行うような会社がありますという前提の説明をしましょう。あえて非現実的にするために、おもちゃロボットがなぜかヒットしたという会社を考えます。画像素材は誰が見てもご存知のイラストやさんです。ありがとうございます。

まず、この会社には営業部門があります。製造したロボットを、卸売や大手小売業者に販売します。営業部門では、「ロボットさんま1号 x 24個」のように、この会社の商品を、通常は複数個まとめて出荷するという作業を行います。営業部門が考える関心ごととは、ともかくたくさん販売して、売上を伸ばすことです。また、季節性のある商品や何かイベントなどでの売上の波が来そうな場合に、別の部門との折衝を行なって在庫確保などもしているかもしれません。

一方、この会社には製造部門も持っています。製造はどうやら外注していないようです。製造部門は、当然ながら、商品を1つずつ作ります。まとめてどこかに在庫しますが、どうやら出荷計画を作ってそれに基づいて製造をするという大きな流れを持っているようです。この部門の関心事は不良品がないなどの製品品質を高めることが大きいようです。

さらにマーケティング部門もあります。マーケティング部門なので、現状の商品を訴求するためのさまざまな活動が行われていますが、一番大きなミッションは新たな市場を作るということを経営側から命じられています。この部門にとっては、商品1つ1つは関心ごとではなく、商品という大きな概念そのものを扱っていると言えるでしょう。

もちろん、この会社には経営陣がいます。もちろん、経営陣は会社の収益を確保し高めることが一番の関心事になりますが、どうやらこの会社はハイテクな商品を作っているように見えて、情報システムは部門ごとに作ってしまっているようで、連携はしていないようです。

このような会社で、部門にまたがって使える業務システムを設計するということが発生しました。ということで、設計を進める上で何を考えるかということを考えてみたいと思います。これくらいの内容なら、すぐに作れるよとおっしゃる方もいらっしゃるでしょうけど、そういう方が頭に即思い付くような「テーブル構成」がどのように導き出されるのかを、「表を作ってみる」というアクションから考えてみたいと思います。

[DBデザイン#3] 表のモデル

昨日このポストを書いた後、サーバーのメンテを長くやってないなと思ってアップデートをかけたら、一気に起動しなくなってしまってデータが消えてしまいました。ある程度はバックアップしてあるので、メッセージは一昨日分まで、画像などは2019年までしかなかったです。まあ、でも、Ubuntu Server 20.04に入れ替えて心機一転です。ただ、同じ内容を書いても、日が変わると内容が違って来そうで、いいのか悪いのか、ともかく昨日書いた内容を思い出しつつ、変化しながら書きます。

データベースの設計を行う上で、まず、データをどのように見るのかという基本的なことで、表を出しました。表に対して、レコードやフィールドといった名称を定義しました。多くの方が表計算ソフトを使っているので、表は便利かつ有用であるというのは理解はしていると思いますが、それが「なぜ?」を突き詰めると実はなかなか難しいということも説明しました。ほとんどの方が、表にまとめて、あるいは表にまとまったものを参照して、何か目的を達したり、より効果的に作業ができるなどの成功体験があるということがあるでしょう。そうした体験から有用性を理解しているということが、ともかくの理由でした。

なお、数学的な世界では、集合の仕組みを利用して、表そのものをきちんと定義するということは可能であり、いわゆるデータベースの教科書ではそうした集合論をベースにした表の定義が最初の方で説明されています。いきなりその辺りで挫折する方も多いかもしれません。また、そうした高度に抽象化された世界が実際のデータベース設計にどこまで役に立つのと問われると、最初のとっかかりとしてはやはりきついと思います。データベースの設計をある程度理解した時、そうか、基本は集合だったよなということを思い出すことで理解が深まるということもあります。

いずれにしても、まずはデータを表として記述することで、ある程度コンパクトに、そして存在するデータを余すことなく記述できます。つまり、Excelでなんでもできるでしょうというあたりの考えに近いかもしれません。つまり、表はそれで完結した世界です。しかしながら、私たちは書ききれないほどの大量のデータを扱いたいのでデータベースを使おうということがあります。この時、データベースは表形式にデータを扱いものの表の縦横を自由に使うのではなく、まずは行に相当するレコードに区切り、レコードはフィールドとして分割され、フィールドにデータを入力できるということを説明しました。その状況をツリーのように記述できます。ここでの線は、導出可能であるということを意味しています。つまり、あるレコードが決まれば、そのレコードからフィールドの値が取り出せるということです。プログラミング言語で処理をすると、実際にそうした側面が強く出ますが、ここではモデルの段階から表はレコードの集まり、レコードはフィールドの集まりであるということを意識したいと思います。

このように、表は階層的なツリー図で表現できるということであれば、表とツリーは同一のデータを示していると言えます。ただ、ツリーの方が実際に描画するのは大変そうですが、概念としては同一のものを示しています。

ここで、具体的にデータが存在するのはフィールドです。レコードもデータの集まりではあり、要するにフィールドの集合ではありますが、単一のデータを持つわけではありません。その意味では、レコード、そして表自体も存在がちょっと抽象的になります。それをまずはあえて楕円形のオブジェクトで書きます。レコードには名前等がないので、便宜的にレコード1などと数字付きで書きますが、表そのものには「住所録」といった名前があります。

ここで、表自体の設計情報を記述する場合、もちろん、全データを書くというのは設計図としては複雑すぎて意味がありません。設計、つまりモデルは、興味のある対象に絞った情報を集めたものというのが原則です。それを、必要な情報に捨象するといった言い方をします。つまり、「どんな表なのか」ということを如実に示す情報が欲しいわけです。

ここでの表を見てみると、まず、どのレコードも同じフィールドを持っています。そのフィールドの実データではなく、フィールドの名前を使って、どんなフィールドが存在するのかを記述してみると、次の図のようになります。どのレコードからも、同一のフィールドが存在するので、全レコードについて記述する必要はなく、レコードは1つだけで良いでしょう。

ここでさらに、表はレコードの集合であるということが決められているということでああるのなら、レコードが存在しますということをモデル上に表現する必要はないとも言えます。ただ、「しない」わけではなく、そういう表現をすることもありますが、ここではシンプルな表はみんな同じ考えで見ているとして、レコードの存在はあえて書かなくても同じフィールドを持つものが複数存在するということを前提とします。すると、残ったものは、表の名前と、フィールド名です。これらを、ちょっとわざとらしく、ボックスに書いてみると次のようになります。

これは、ER図のエンティティのようでもあり、クラス図のクラスのようでもあります。いずれにしても、こうした記述が住所録を管理する表の設計として認識できます。元は表ですが、それを階層的に見た上で、必要な情報だけを残すと、このようなものができます。データベースの設計者は、このボックスを見ることで、実データが表として展開されて、たくさんのデータが入るという状況を想定し、それが実際のシステムの用途に合致したものかどうかを検討しながら設計を進めるということができるのです。

ここで、命名が「住所録」といった集合的なものになっている点にちょっと気に掛かる人もいるかもしれません。ここはある意味好みの問題なのかもしれませんが、表に対して名前をつけているのか、レコード1つに対する名前なのかで分かれるところだと思います。データベースの設計では、レコードとして実現されるので、表とレコードは最初から組み合わされているので、ER図のような世界に入り込めるのです。これがクラス図であれば、「住所録」ではなく、「顧客」などの単一レコードを示す名称をつけ、さらに「顧客リスト」といったクラスを考えて、顧客リストは顧客の集合、つまり表とレコードの関係のような記述をする方が落ち着くと思われかもしれません。クラス図の方が抽象度が高いので、いろいろな記述のバリエーションは考えられます。これは、結果的には設計者がどう決めるかの問題です。少なくとも、1つの設計の中で、ボックスの粒度をどう扱うかを統一した上で、そのルールが他の人にわかるようなコミュニュケーションをしているかどうかということです。

私自身は、クラス図で書くことが多いのですが、いきなりデータベース設計するのではなく、まずはドメイン分析からスタートして詳細化してデータベース設計に持ち込むので、その結果クラス図で記述する異なってしまいます。もっとも、使っているツールのastah* professionalは、クラス図からER図を作成できるので、単にツールで書き換えればER図になります。また、クラス図で記述すれば、オブジェクト図を書くことができます。オブジェクト図はクラスに基づくオブジェクトであり、つまり実データが入ったボックスを記述できます。その仕組みにより実際のデータを当てはめてみて、それが意図した状態を表現できているかということを、検証することが可能です。複雑なデータであれば、そうした設計から実データ展開した検証をしたくなりますが、クラス図とオブジェクト図で、作業が可能です。クラス図でスタートしたら、結果的にクラス図で記述したデータベース設計になり、自分としては違和感ないのですが、怪訝な顔をされることもありますね。

次回からは、架空の会社の業務を想定した上で、同じ名前の対象物に対して、部署ごとに管理したい内容が違い、結果的に違う表が必要になるというお話を何回かに分けて行います。

[DBデザイン#2] データベースのモデル

データベースの話を進める上で、基本的な概念として何をベースに話をスタートさせるかをきちんと決めておきましょう。用語の整理というよりも、基本概念の整理がまず必要です。以下の図は、どこかで見たことがあるようなと思われる方もいらっしゃいますが、大して難しい概念はないと思います。まず、これを見て、直感的に、住所録、つまり複数の人の名前、住所、電話番号を「表にしている」と見てもらえると思います。

この表がデータベースのごく基本的なモデルとなります。表にまとめることで、人間がデータを参照したときに理解、あるいは活用がしやすくなるということがあります。データがを混沌と記録していたとして、記録はできているとしても、そこから特定のデータを探したり、データの傾向を求めるということは大変なことだったり失敗したりということになります。一方、データをきれいに整理しておけば、容易に検索したり、確実に集計したりということが期待できます。その整理された形式が表です。

ここで、Excelなどの表計算ソフトを引き合いに出して、「表は良い」ということを議論することもできるでしょう。表にしておくことで、オーバーな言い方ではありますが、多くの人が成功体験を積んでいるはずです。色々な利点が見出されている表というのものをモデルとして考えるということが出発点になります。もっとも、それは鶏と卵の議論ではないかということも言えるかもしれません。リレーショナルデータベースの理論が最初に発表されたような時期だと、表というモデルを考えること自体は単に1つのアイデアであり有用性までは実証されていないとの見方もあったようです。後々、ソフトウエアとして実装された上で、リレーショナルデータベースの有用性が証明され、理論と実際が相互に発達してきたという経緯もあります。

結果的に「まず表で始めます」となると、表が便利なのは常識だろうということで理由が吹っ飛んでしまいますが、表が便利なことを突き詰めて考えるのはやはりかなり難しいとも言えます。感覚的に、理解しやすく、しかも、大量のデータを扱えそうだというあたりの考えが出発点にあるということは、それほど不自然ではないと考えます。

さて、表とは言ってももう少しその構造を細かく見ましょう。非常に重要なことは「1人の人が1行」ということです。つまり、この行のことを「レコード」と呼ぶとして、1レコードが何を表しているのかということが非常に重要です。実は、これが決まればデータベースは実装可能ですが、1レコードを示すものが揺らいだり、間違っていると、データの記録がうまくできません。このことは改めて説明しますが、ここでは住所録は1レコードが1人であるということに注目します。そして、1人のレコードには、複数の「フィールド」があります。フィールドには「フィールド名」がつけられています。

1人の人の住所録を管理する上で、ひたすら名前や住所を書き並べても良いのですが、よく整理された状態というのは、一定の基準で情報が分離され、整頓されているということであると言えます。基本的に1人の人は、1つの名前があって、1つの住所があるということにここではしてください。だとしたら、名前と住所をごちゃ混ぜに記録するよりも、名前の枠、住所の枠で分離しておく方が、整理されたように見えます。つまり、ある特定の「属性」の情報「だけ」が取り出したりあるいは入力しやすくなっている方が都合が良いということが言えるはずです。もし、ごちゃ混ぜだったら、その混沌としたデータから一部分のデータ(例えば、名前だけ)を取り出すことが大変だったり、あるいは不可能だったりします。よって、フィールドに分離分割され、フィールドに実際のデータを入れておくという仕組みが作られたわけです。そして、フィールドという単位で処理をすることにより、うまくいけばデータの種類に関わらず、必要なデータだけがポンと出てくるということができるはずです。

ちなみに、レコードについては、行、ロー、タプルなどの言い方があり、フィールドについては、列、カラム、属性、アトリビュート、プロパティなどの言い方もありますます。一部のコミュニティではその言い方を間違えると白い目で見られるということも以前はあったようですが、表形式でデータ全体を考えるという概念上は概ね同じものを指しています。一連の記事では、レコード/フィールドという呼び方で進めます。

表計算ソフトだと、縦横にセルが並んでいるのですが、見かけは同じ表でも、データベースでの表は、まず、表をレコードごとに分割されていて、そのレコードにフィールドが存在するという見方をするのが良いでしょう。表の一部分を自由に扱うということもある意味はできますが、階層的に記述したら、以下の図のように、レコードの方が上位概念になります。この図の線は、正確には「導出可能」という意味です。ある表である「住所録」があるとき、その住所録からレコードに辿り着き、特定のレコードからフィールドのデータに辿り着けるというのが導出の具体例です。実際にそういうプログラムを記述できると言っても良いでしょう。視覚的にいえば、表をまず横方向にスライスして、そのスライス1つ1つについて、縦方向にスライスすることで実データに辿り着くという感じです。

階層の図(「ツリー」と呼びましょう)ではフィールド名は省略していますが、最初の表と、この階層図は、概念的には同じものを示しています。同じとは何か? ここでは「同一データ」と言っても良いでしょう。「表とツリーは同一である」ということは理解しづらいことかもしれませんが、一方で当たり前すぎて意識していない人も多いかもしれません。住所録は表で記述できますが、ツリーでも記述できるので、同一なのです。もちろん、表のほうがコンパクトで扱いやすそうです。ツリーが優れている理由はここでは明確にはありませんが、ツリーは関連性を明示可能です。つまり、表/レコード/フィールドという階層を明確に示すことができています。

ツリーを見ていると、フィールドの集合がレコードであり、レコードの集合が表であるということが明確にわかります。ここで、フィールドだけが具体的なデータを記録できていて、レコード自体はそのフィールドの集合という位置づけになります。なので、もちろん最初のレコードを「鈴木一郎」という名前で呼んでもいいのですが、レコードを特定する情報はここでは明確ではないので、便宜的に「レコード1」と記述しています。なお、レコードの特定の問題については、今後、色々な視点で説明をすることになります。

集合(set)といえば数学、数学といえば「嫌い」という人も多いかもしれませんが、集合論の真面目な議論に入らなくても、日常的な感覚の範囲では頑張って理解しましょう。ただ、集合と言うと深い議論があって、その1つは「集合には要素に重複はない」と言う定義です。集合の基本的な定義は「お互いに区別できるものの集まり」となっています。住所録の場合、重複したデータ、つまり全く同一の2つの行があった場合、用途上それは2つ存在している必要は全くなく一方は消したりないものとして扱うことは問題ありません。なので、レコードの「集合」が表なのです。また、フィールドについても、1つしかない名前を2つ以上のフィールドに入れたところでそのうちの1つしか必要ないので、フィールドの「集合」がレコードになるのです。この辺り、現実と数学の定義がよく合います。集合の考え方がリレーショナルデータベースの理論の基礎になっているという点は決して無視できない時事です。ここでは細かく議論しませんが、集合の要素は順序は問わないという定義もやっぱりデータベースの表といろんな意味でよくマッチングします。ちなみに、今回は数式は出しませんでしたが、先々では数式も出ると思います。その方がわかりやすいこともありますので、その時はなるべくわかりやすく説明するように心がけますが、数式があっても驚かないでください。

数学としての集合は有名ですが、その仲間のようなものも数学で定義されています。要素の重複を許すものをバグ(bag)あるいは多重集合(multiset)と呼ばれています。また、重複を許しつつ順序も情報として持つものを列(sequence、list)と呼ばれています。さらに重複は許さないが順序も情報として持つ順序集合(ordered set)もあります。これらも集合を基にした数学の理論は展開されています。ですが、プログラムができる方は、むしろ配列などとして理解されており、物理的な意味でデータを実際にこの形式で扱っているとも言えるので、抽象数学よりも具体的な世界での理解はされているのではないかと思います。数学に興味のある方はその辺りも書籍などを当たってみると良いでしょう・・・と言いつつ、この種の数学の書籍はかなり気合いと時間をかけないと理解に至らないのは確かですね。

次回は、表をツリーにしたことで、ER図の一部の定義に到達できることを説明しましょう。

[DBデザイン#1] データベースデザインについて書く

データベースデザインを、ここでは、「リレーショナルデータベースでシステム開発等を行う場合に、データベースのスキーマ、つまりどんなテーブルやフィールドを用意すれば良いのか」と言う問題であると定義します。データベースそのものの設計ではなく、データベースを利用する場合の問題です。RDBで開発をしている人は、どのように設計をすればいいのかと言うことが大変難しい問題であることはよくご存知でしょう。FileMakerを使って「簡単にテーブル定義ができます」となっていても、操作が簡単なことで設計が適切にできるかどうかは定かではありません。単純なシステムならともかく、今時は手元でやっている複雑怪奇でどうしようもない作業があるからコンピュータにさせようと言うのが動機としては一般的です。したがって、目的とするシステムを実現可能なデータ構造も複雑化しがちです。そう言うことで開発をしようというと、ベテラン、エースあるいはアーキテクトなどと呼ばれる専門家などがスキーマ設計を行うことになります。彼らは、多くの事例にこれまで取り扱ったという経験があり、複雑でどうしようもなさそうな要求をうまくシステムが飲み込んでしまうようなスキーマを作ってしまいます。

そうしたスキルを得るにはどうすればいいか? 経験を積むと言うこともあります。しかし、経験を積んでもそれができない人もいます。理解をするには理由を知ることが重要です。簡単な問題には「なぜ?」に対する答えは言えるのですが、非常に複雑な問題や、要件が怪奇すぎて微妙な問題に対するうまい解決策などをスキーマ設計者が出してきたとき、なぜそうなのかと言うことは設計者もうまく説明できないかもしれません。もちろん、理由があるのですが、知識を知らない人に説明できるかというとなかなか難しいと言うのが実情でしょう。もちろん、そう言う場合に頼りになるという意味では悪くはないとも言えますが、「自分もそうしたスキルをつけたい」と思ったらどうすればいいのでしょうか?

そう言うわけで、いろんな書籍があり、セミナーなどもやっていて、それらで勉強すればなんとかなっているという人もいるでしょうし、やっぱりわからなかったという人もいるでしょう。私も、ある有名なデータベース設計者のセミナーを参加して気づきました。そのかたの示す設計はもちろん、なるほどと思うところもあるのですが、理由を仔細におっしゃらない場面も多々あり、要するに「常識的にはこうなりますね」的な説明で終わってしまう場面もあったからです。その理由を知りたい、理由を知って応用したいと思うのが通常かと思いますが、やはりデータベース設計の世界は、どうもまずは経験を積んだ人の知見が主なナレッジということになってしまうのでしょう。

私自身はその答えはもう持っていて、クローズドなセミナー等で少しはお話ししています。また、そういうコンテンツを持っているのなら、それをビジネス展開してはどうかと思われるところかもしれません。少しはそう思っていたのですが、いろんな状況が重なり、「そうだ、淡々とブログに書こう!」と思った次第です。不定期にこの話題を積み重ねて行こうと思っています。まず、近々は、以前に所属した会社の社内セミナーで話そうとしていた内容を文章にまとめようと思っています。大まかに説明すると、「同じ名前のものが部署によって異なる対象になる」という事例から、それらはテーブルを分離しないと管理できないという話です。ドメイン駆動開発の世界でのユビキタス言語の考え方を、データベース設計のある側面に適用したお話しです。

そういうわけで、データベースデザインについて書くことにしました。