ホームリレーショナル・データベースの世界セルコ・セレクション


テーブル VS ファイル、行 VS レコード、列 VS フィールド

Developersdex (2002/07/28), "The differences between fields & columns, rows & records, files & tables")



何が私たちを悩ませるのか


 私たちを悩ませるのは、知らないことがらではなく、誤った知識である。
ウィリアム・グレアム・サムナー


 「大抵の新しいアイデアと同じで」と、おもむろにセルコは書き出します。「関係モデルの一番理解が難しい部分がなぜ難しいかといえば、私たちが既にファイルシステムについて知っていることを、一度頭から追い出す(unlearn)必要があるからだ。」
 私たちが新しい概念について学ぶとき、多くの場合、既知の概念を手がかりにして、それと類比的に捉えようとします。それ自体は、別に間違った方法ではありません。最初はそうでもしなければ、とっかかりさえつかむのが難しいはずです。最初の一歩としては、それでいいのです。しかし、あるレベルまで達すると、自分がよく知っていて使いこなしているはずの概念やスキーマが、逆に新しい概念の理解を妨げることが、たびたびあります。
 関係モデルを学ぶとき、最初に類比の対象に選ばれるのは、十中八九、ファイルシステムです。このモデルが関係モデルと齟齬を来たす理由は、ファイルシステムがあまりに物理的な記憶方法に密接に結びついている概念であるのに対し、関係モデルは極力、ユーザが物理的な記憶方法を意識せずともすむよう、抽象度を高めることを目的とするデモルだからです。ファイルシステムとリレーショナル・データベースの抽象度の違いは、次の四つの側面において現れます。

    (0) データベースはファイルの集まりではない。
    (1) テーブルはファイルではない。
    (2) 行はレコードではない。
    (3) 列はフィールドではない。

 かつて、コンピュータを使ったデータ処理の歴史はパンチカードから始まり、しばらくして磁気テープの時代に移りました。いま私たちが「ファイル」と呼んでいる概念が成立したのもこの頃です。ファイルの最大の特徴は、順序を持つことです。昔は、データ処理を始めるとき、まず最初にパンチカードや磁気テープをソートして順序をそろえる必要がありました。ファイルの内部においても、レコードは行番号で管理されていて、順番を持ちます。従って、データ処理は徹頭徹尾、順番を重視することになります。こういう用途に対応すべく発明されたのが、Fortran に始まる手続き型言語でした。今でも手続き型言語を習うときは、最初にソートのアルゴリズムをいくつも叩き込まれます。
 リレーショナル・データベースは、全くそういう動作をしません。各ユーザは同時にデータベース全体にアクセスできます。一つのステップにおいて一つのテーブルにしかアクセスできない、なんてデータベースは存在しません。ファイルを複数ユーザで共有することはできませんが、まさにその「データ共有」こそが、データベースのポイントの一つです。



ファイル VS テーブル

 ファイルが物理的な記憶媒体に密接に結びついた概念であるのに対し、テーブルは、そうではありません。理由は二つあります。第一に、一つのテーブルが必ずしも一つのファイルであるとは限らないこと。例えば、DB2 は1ファイル1テーブルという方式を使いますが、Sybase は複数のテーブルを一つのファイル内に持ちます。そして第二に、ファイルには行の順番があり、それゆえ行番号によるアクセスが可能ですが、テーブルは行の順番を持ちません。テーブルは行の集合であり、集合の要素に順番はないからです。それゆえ、SQL に記述される演算の中に「ソート」は存在しません[1]。DBMS が内部処理としてソートを利用することはあっても、ユーザからは隠蔽されています。また、「ORDER BY句があるじゃないか」と思われるかもしれませんが、あれは厳密には SQL の一部ではなく、カーソルの機能です。
 「順序づけられたレコードを持つ物理的ファイルというのが心理的モデルになってしまうと、それを振り払うのは難しい。データを見るといつでもそれが物理的な順序を持つと思いこんでしまう」というのが、セルコの観察です。これは、私の経験に照らしても正しい洞察だと思います。一度心の中に出来上がったモデルを捨てるというのは、なかなか難しいものです。特に、それでも「できなくはない」という程度に応用力のあるモデルの場合、あえて新しい土地へでかけるのが億劫になってしまいます。

 また、テーブルとファイルの相違点として、セルコは、テーブルが物理的・概念的なエンティティを表すのに対し、ファイルは様々なエンティティが放り込まれた雑多な概念だという点を挙げています。いわく、テーブルは「純粋」データだが、ファイルは「混合」データである、と。
 セルコがテーブルの表すエンティティを、物理的なものと概念的なものの二種類に分けているのは、顧客、従業員、在庫といった普通の物理的エンティティと、契約や購買といった、それらの関連を表す関連エンティティの違いを念頭に置いているからです。
 この記事でもそうですが、セルコはよくテーブル名を複数形(または集合名詞)で名付けるべきだと主張しています。従業員テーブルは、「Employee」という単数形よりも「Employees」という複数形や集合名詞「Personnel」のがいい、ということです。その方が、テーブル名を聞いたときに個々の従業員の心的イメージが浮かばないから、テーブルが集合的な存在であることを強調するのに相応しい、というのがその理由です。なかなか傾聴に値する細やかな助言です。特に、そもそも単数・複数の区別に無頓着な言語を使う私たち日本人にとっては、この区別そのものが持つ意味を考えさせられるという点でも重要な着眼点です。



行 VS レコード

 行はレコードではありません。なぜなら、レコードがアプリケーション・プログラムによって定義されるのに対し、行はデータベース・スキーマによって定義され、プログラムとは一切関係ないからです。このことは、空テーブルと空ファイルを比較するとよく分かります。0バイトの空ファイルは、どれも皆同じようなものです。違うのはファイル名だけで、列もなければ行もありません。一方、空テーブルは列を持ち、制約を持ち、セキュリティ権限を持ちます。ただ行がないだけです。それゆえ全ての空テーブルは全て一つ一つ別物です。空テーブルは、集合論の空集合に対応するものです。一つ、集合論の空集合と SQL の空テーブルの差異があるのは、集合論には空集合は一種類しかないのに対し、SQL では各テーブルが異なる構造を持つために、テーブルの数だけ空テーブルが存在することです。
 行とレコードのもう一つの違いは、行が全て構造的に同じで、それゆえ各行は全て「同じ種類」の存在であるのに対し[2]、レコードはサイズもバラバラだし、データ型や構造も一致している必要がないことです。例えば、パスカルの Varint レコードや、C言語と Cobol の構造体を使うことで、ファイルに含むデータ型をユーザが自由に指定できます。



列 VS フィールド

 列とフィールドの違いも、行とレコードの違いとよく似ています。すなわち、列を定義するのがプログラムであるのに対し、列はデータベース・スキーマが定義します。また、上の方で、テーブルと行には順序の概念がない、という話をしましたが、同じことが列にも当てはまります。フィールドにアクセスする際には、読み込み/書き出しの命令に記述される順番やバイト位置が重要ですが、SQL において、列は名前でのみアクセスされます。SQL を書くときに、列が物理的にどういう順番で格納されているかを意識する必要はありません。
 もっとも、SQL においても、「SELECT * 」のような書き方をした場合には、列の順番に気をつける必要がありますし、ORDER BY句でも「ORDER BY 1, 2」のように、列番号でアクセスすることが可能になっています。しかし、アスタリスクは結局のところ列名に展開される省略形に過ぎませんし、ORDER BY句で列番号を使う方法は、SQL-92 で削除対象のリストに挙がっています。将来的には各実装からも削られる可能性が高いでしょう。
 NULL の存在も、ファイルシステムとデータベースの大きな相違点です。フィールド、レコード、ファイルは、失われた情報を示すためのマークをサポートしていません。普通はスペースやクォーテーション記号で囲むことで表現します。しかも、フィールドには、リレーショナル・データベースでいうドメイン制約に当たる機能もありません。これはまだ実際の DBMS も不十分にしかサポートしていない機能ですが、データベースでは スカラ型や CHECK制約を使うことで列に含まれうる値の領域を制限できます。翻ってフィールドには任意の値が含まれます。整合性のチェックはアプリケーションに一任されることになります。これはコーディングにおいて、さして重要な機能ではないのに大きな労力を要する部分になります。



データベース VS ファイルシステム

 セルコはこの節を「ファイルは受動的な奴だ」という言葉で始めています。なかなか名言です。確かに、プログラムがファイルにどんな仕打ちをしても、大抵の場合、何も不平不満を言わずにじっとしています。ファイルはまた、他のファイルたちがどんな仕打ちを受けているかについても無関心です。
 これに比べると、データベースというのは相当口やかましい奴です。少しでも制約に違反した更新を行なおうものなら、すぐにエラーを返してきます。データベースには、CHECK制約や参照整合性制約、トリガーといった、ユーザのやることなすことに口を挟む豊富な手段が揃っています。しかも、更新を受けているテーブルだけでなく、その他のテーブルとの関連までチェックされます。「データベースはファイルの集合ではない」とはそういう意味です。テーブル同士が相互に状態をチェックし合う、能動的なシステムです。



まとめ

 ざっと、ファイルシステムとリレーショナル・データベースのモデルの違いについて説明してきました。こういうモデルは、優劣を簡単に比較できるものではありません。ですが、色々なタイプのモデルを頭の中にストックしておくことは、エンジニアにとってきっと有用でしょう。世界は一つのモデルで割り切れるほどに単純ではありませんが、ワインバーグが「クリスマスに金槌をもらった子供はそれで何でも叩きたがる」と言ったように、私たちはどうやったって手持ちの道具を使ってしか問題に対処できないからです。引き出しは多いに越したことはありません。金槌がどれほど使い慣れていて強力な道具であっても、ノコギリやペンチも使えてこそのエンジニアです。




[1] SQL がソートを使わず、テーブルを集合として考えるということの具体例は、例えば「集合で考える」の「例題:歯抜けを探せ」を参照。

[2] 行の構造が全て同じである理由は、関係を一つの多項述語として考えると分かりやすくなります。あるテーブルに含まれる行は全て、一つの同じ述語から生成された命題として考えられます。


Copyright (C) ミック
作成日:2006/07/30
最終更新日:2006/08/01
戻る