« 製造指示の設計と実装 (3)外作 | トップページ | 「売上伝票」を問い直す »

2013.04.15

アンチパターン「成長する主キー」

 我ながらしつこいが、またまたテーブルの主キーに関する話題である。「複合主キー」を毛嫌いする開発者がいるとすれば、その根拠はおおむね2つある。「ID等の単独主キーにしておけば、主キーの仕様変更に振り回されない」、および「複合主キーにすると実装が煩雑になる」だ。それぞれについて反論しよう。なおこれらの他に「ナチュラルキーを主キーにすると値が変わったときに困るから、複合主キーはダメ」と説明されることがあるが、こちらは非論理的なので取り上げない(詳しくは「ナチュラルキーを主キーにしてはいけない」を参照)。

■成長する主キー

 まず「ID等の単独主キーにしておけば、主キーの仕様変更に振り回されない」についてだが、この主張は一面的には正しい。じっさい私自身、複合主キーの仕様変更に振り回された思い出がある。

 新人の頃、ある重要なテーブルを処理するアプリをプログラミングしていた。仕様書にしたがって検索すると、どうも対象レコードが1件に特定されないような気がした。というより、現在の主キーでは遅かれ早かれレコードを追加する際に一意制約にひっかかってしまいそうだった。

 主任SEにそこらへんを相談してみたところ、彼はこともなげに答えた。「なるほど。では、○○も主キーに含めてくれるかな」私は自分の心配が的外れでなかったことに満足して現在の主キーに項目を追加し、関係するアプリを作り直した。

 その後でまた心配になった。変更された仕様でも、遅かれ早かれレコードが重複するような気がしたからだ。それで再び尋ねると「なるほど。では、△△も主キーに含めてくれるかな」と言われて、また修正した。ところがそれでも重複する可能性が原理的には残っていることに気づいて、また尋ねた。すると「なるほど。ではレコードの追加日時を主キーの最後に置いてくれるかな。それなら重複することはないから」と言われた。

 その頃の私は若かったし、DB設計のあるべき姿もわかっていなかったので、そんな指示にもマジメに従っていた。とくに主キーの変更はインパクトが大きく、関係するアプリ群の作り変えに苦労したが、それでもシステム開発とはこんなものなのだろうと思っていた。

 その後、自分でDB設計するようになって、主キー設計の的確さが開発生産性やデータ品質に重大な影響を及ぼすことに気づいた。私が新人の頃に経験したアレは、あきらかに稚拙なやり方だったのだ。レコードの主キーを決める――これはDB設計における要諦である。「一意にならないからナニカを付け足す」では、設計に必要な検討を怠っていると批判されてもしかたない。それは夏場の雑草のようにすくすく伸びて周囲を閉口させる。このアンチパターンを「成長する主キー」と呼ぼう。

■「ID方式」は事態を悪化させる

 「そんなことで苦労するのはバカバカしい。初めからauto-incrementのIDを主キーにしたらいいじゃないか」だって?はいアウト。その設計スタイルは事態をさらに悪化させる。

 単独主キーだろうが複合主キーだろうが主キーには、リレーション中の各レコードに対して一意制約を与える(一意性*1)だけでなく、レコードのライフサイクルにおいて値が変化しない(不変性)という重要な性質がある。一意でないとしたら対応レコードを特定できないし、値が変化するとしたらそれを参照する側とのリンクがはずれるからだ。

 ところがID方式では、ID以外のフィールドで構成される本来の一意性や不変性を考慮しないままでDB設計できてしまう。それはちょうど、重力を考慮せずに高層ビルを設計するようなものだ。仕事としてはたいそう簡単だが、その成果は危うい。

 たとえばそのテーブルは本来は、キー項目aとbの組み合わせで決まる属性項目cの値を管理するためのものかもれない。すなわち、

c=F(a, b)

の関数従属性やドメイン制約*2を実現するために(1)のテーブルが求められているのかもしれない。にもかかわらず、IDを主キー(一次識別子)として、a,bを重複可かつ変更可とする(2)のような設計がなされる。

(1) [Table1] a,b, c

(2) [Table1] ID, a, b, c

(3) [Table1] ID, {a, b}, c

 百歩ゆずって、(3)のように{a,b}にユニーク制約を付与して、かつ、システムが完成したときにa,bの値を修正可能なアプリが存在していなかったとしよう。それでもまだ危うさが残る。ID方式では(1)の正規形が申し送られないので、「Table1上のa,bの値は属性項目でありながらも変更不可」という制約を保守担当者が認識できないからだ。

 すなわち、a,bの値をアプリ上で修正できるようにしたいとユーザが依頼したとき、保守担当者にはそれを断る理由がない。ユニーク制約さえ保全されればかまわないだろうと判断され、アプリが改修される。かくして遅かれ早かれデータベースの整合性が失われる。

 このようにID方式では、DBの整合性を失わせるような更新(更新時異状)の危険性が「潜行」する。設計方針としてはシンプルで実践しやすいし、「成長する主キー」に悩まされる心配もないし、一見すると機嫌よく動いているようにも見える。しかし、データが原因もわからないままゆっくりと腐ってゆく。問題が最初からビジブルな「成長する主キー」よりも、ある意味ではタチが悪い。

 ゆえに、少なくとも論理設計の段階では、IDに頼らず、複合主キーを要求する複合概念を含めてしっかりデータモデリングすべきだ。その後で、必要に応じてサロゲートキーを組み込めばよい。いくら「成長する主キー」に振り回された経験があるとしても、論理設計の段階でID方式に逃げ込んではいけない。行きはヨイヨイでも帰りがコワイからだ。

■まとめ

 以上を理解してもらえば、複合主キーに反対する2つ目の理由「複合主キーにすると実装が煩雑になる」の無意味さも理解できるだろう。この理由で複合主キーをいやがるのは「鉄筋はなるべく減らしてくれ。施工が面倒だから」と言うのと変わらない。強度要件やデータ要件として、工学上必要なものは必要。それだけの話だ。そもそも、たかだか複合主キー程度で実装が煩雑になるような開発基盤は、どう考えても業務システム開発には向いていない。

 とはいうものの、「鉄筋を1本しか許さないような工法」が諸般の事情で強制されることがあるかもしれない。そのときは、スジカイやカスガイ等を駆使して建物の強度を慎重に補えばよい。「単独主キーしか許さないような開発基盤」が諸般の事情で強制されることもあるかもしれない。そのときは、更新時異状が起こらないように慎重に補強すればよい。ただし繰り返すようだが、複合主キーを含む正規化されたデータモデルが手元になければ、補強にも保守にも失敗する。

 結論。少なくとも論理設計のフェーズでは、複合主キーを忌避してはいけない。同時に、「成長する主キー」のようなハタ迷惑な仕事をやってもいけない。DB設計は「業務上の概念をコンピュータ上に定着させるための魔方陣」を描く作業である。それは想像以上に面白くも難しく、そして因果な仕事だ。


*1.一意キー(ユニークキー)を「単独主キー」と理解している技術者がいるが、それは初歩的な間違いだ。単独主キーだろうが複合主キーだろうが「レコードを特定できるキー」が一意キーである。テーブルは複数の一意キーを持ち得るが、その中でもデータのライフサイクルを通じて値が更新されないものが「主キー(一次識別子)」である。

*2.定義域(ドメイン)制約のこと。ここでは、aとbのそれぞれに定義域がある他に、それらの値の「組み合わせ」が定義域を成していることを示す。cのような属性項目を含まないテーブルでは関数従属性は成立しないが、ドメイン制約は成立する。

|

« 製造指示の設計と実装 (3)外作 | トップページ | 「売上伝票」を問い直す »

コメント

「Table1上のa,bの値は属性項目でありながらも変更不可」という制約を保守担当者が認識できない場合って、
外部にシステム開発を依頼する企業からすると最悪の状況に陥りそうですね。
システム開発を依頼する先を変えたりして制約が引き継がれず、データがゆっくりと腐ってゆき、気付いた時には責任を追求する先がはっきりしなくなっている。
全ての責任は社内の保守担当者が負わされるはめになりそうで、すごくコワイ話に思えてきました。

投稿: iwajun0 | 2013.04.15 14:53

iwajunさん

どもです~(^^) そうですよね。問題があることは明らかなのにそれを特定できないまま、延々ともぐら叩きを続けるしかない。ID方式はむしろより高いスキルや慎重な文書化が求められるアクの強い設計手法なんです。見かけのシンプルさに騙されてはいけませんね。

投稿: わたなべ | 2013.04.16 07:42

ちゃんとDB設計して稼動7年経過したシステムの保守を担当していますが、先週DBの主キー追加を顧客に依頼したところ「人工キーを追加してそれ一つを主キーにしてほしい」という回答が来ました。
何か実現したいことがあるのか尋ねましたが、社内共通部門の指摘らしく、明確な理由が分かりませんでした。

まあ壊れる可能性の低いデータだからいいんですけど、なんかベストプラクティスみたいな風潮が蔓延したら、困るなぁ。

投稿: Web開発者 | 2013.04.16 19:24

Web開発者さん

社内標準策定に「ID方式主義者」が関わっているんですかねえ。そんなやり方では中学生でもDB設計できるし、ユーザは自分たちの首を絞めるだけってことも理解していないのでしょう。やはり人は痛い目に会わないと学べないんですかねぇ(><)

投稿: わたなべ | 2013.04.16 23:10

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: アンチパターン「成長する主キー」:

« 製造指示の設計と実装 (3)外作 | トップページ | 「売上伝票」を問い直す »