設計者の発言

業務システム開発とデータモデリングに関する語り

サロゲートキーにこだわるデータモデルの異様さ

 サロゲートキーは「ワサビ」のようなものだ。ある種の料理を引き立てるため、熟慮のうえ利用される。どんな料理にもワサビが強制されるとしたら、異様な食卓になるだろう。同様に、どんなデータを扱う場合にもサロゲートキーが強要されるとしたら、異様な情報管理システムになるだろう。

  その異様さはさまざまな例で示せるが(参考記事「Railsは新人教育に向いていない」)、今回は「予実管理」のモデルで眺めてみよう。まずはまともな例(図1)。期間別の管理項目が、年月を含む主キーで与えられるテーブル上に保持されている。業務システムではふつうに見られるものだ。

 図1.予実管理のモデル Model1

 さまざまなリソース毎に期間別の計画値を設定して実績値と比較することは、業務システムの日常的な役割のひとつである。期間別の計画と実績の乖離を見るというのは、業務上の管理レベルを高めていくための常套手段だ。実績値の集計元となるトランザクション(ここでは売上実績)には、集計単位に関連付けされるための外部キー(ここでは{顧客ID,年月}と{商品ID,年月})が付与されることになる。

 このモデルの主キーをすべてサロゲートキーに置き換えてみよう(図2)。一目見て異様さがわかるだろうか。異常ではないにせよ、異様なのだ。

 図2.サロゲートキーに置き換えたモデル Model2

 まず「年月」が「ID」に置き換わっている点にギョッとさせられるが、考え方によっては許容できそうだ。IDがユリウス日ならぬユリウス年月のような値をとるとすれば、和暦だろうが西暦だろうがイスラム歴だろうが、年月はIDから導出可能な項目とみなせるからだ。無理やり感はあるが、このモデルではそのように想定してある(導出項目はカッコ付きで示されている)。

 ここでの決定的な違和感はやはり、「顧客ID+年月」や「商品ID+年月」といった複合主キーが「ID」の単独主キーに置き換わっている点にある。そのため、それぞれのテーブルの意味がひどくわかりにくい。テーブル名とフィールド名を手がかりにあれこれとブンガク的に想像するしかない。また、売上実績上で参照関係の基礎となる「顧客別サマリID」や「商品別サマリID」にもその値設定について途方に暮れる感じがある。集計処理は無駄に複雑化しそうだ。意図的な正規化崩しとしてユニーク制約や更新不可制約が付与されているとしても、モデルの異様さは減じない。なぜそれほどまでしてサロゲートキーにこだわるのか、というチグハグな印象がつきまとう。

 利用することが決まっている実装基盤がIDの主キーしか許さない、という気の毒な事情があるのかもしれない。そういった特殊な制約のない基盤でシステムを将来的に作り替えることになったらどうするのかと心配にはなるが、それならそれで仕方がない。正規化崩しの一環として必要な手順を踏めばよい。

 ここで私が問題にしたいのは、複合主キーを許す開発環境でも、機械的にすべての主キーをIDにするという設計スタイル(IDリクワイアド)である。すべての料理に機械的にワサビを入れるようなやり方だ。

 サロゲートキーは本来、多めの項目を含む複合主キーを持つテーブルの取り回しを楽にするための便法として導入される。その際には上述したように、本来の複合主キー項目の組み合わせに対するユニーク制約と更新不可制約を付与しなければいけない。そういった「正規化崩しの報い」のわずらわしさと効果とを勘案して、サロゲートキーの導入は慎重に決定される。

 ところが、IDリクワイアドこそが正しい設計方針であると考える人々が存在する。彼らはその合理性を次のように説明する。「エンティティに対するビジネスルールは変化し得る。そういった攪乱に主キーが影響を受けるべきではない。したがって主キーはIDに統一すべきだ」。また、「複合主キーだと、1行を更新すべきSQLのWhere句でいずれかの項目の指定が抜け落ちる恐れがある」とか、「なにごともシンプルイズベスト」といった根拠もある。しかしこれらは高層ビルの設計を担う建築士が、次のように語るようなものだ。

将来どんな地震や台風に襲われるかわからない。予測できない未来の想定に建物の基本構造が影響されるべきではない。また、鉄筋の本数が柱毎に微妙に異なるようでは、間違って施工される怖れがある。したがって、埋め込む鉄筋の本数はすべての柱で1本に統一すべきだ。そのうえで、たとえばビルが傾くなどの状況の変化があれば、俊敏にジャッキや突っかえ棒で補強すればよい。変化を抱擁せよ。

 最初から配慮すべき問題を、状況や要件の変化などとみなしている。これはもう、エンジニアがエンジニアリングの職責を放棄している発言としか言いようがない。技術上の洞察や技量の不足で生じるしわよせを、実装や保守を引き受ける担当者や顧客に押し付けるようなやり方と言ってもいい。

 他にも、複合主キーを「自然キー」と言い換えて批判するといった粗雑な主張も耳にする。たしかに、「コード」のような自然キー(natural key)は値が変化することがあるので主キーには向いていない。ところが、自然キーではない人工キー(artificial key)を組み合わせた複合主キーを、彼らはなぜか自然キーなのでダメと言い張る。意味が分からない。驚くことに、「複合主キーを設定するとデータ操作のパフォーマンスが低下する」といった時代錯誤な主張さえある。

 複雑な工学構築物の設計において、どこかを無理やりシンプルにすれば他のどこかが不必要に複雑化して、トータルの混乱が増えるだけの話だ。たとえ、的外れな複合主キーに苦労させられた経験があるとしても(*1)、複合主キーそのものを否定するのは「羹に懲りて膾を吹く」である。

 もっとも傍迷惑なのは、このやり方だとDB設計が簡単に思えてしまう点かもしれない。扱いやすそうな情報のまとまりについてテーブルとして切り出してIDを主キーとするだけなので、新人でも何やらDB設計をこなしているような気分になれる。しかし、すこし規模が大きくなればデスマーチ確実だ。しかもその場合、デスマーチの原因が稚拙なDB設計にあるという認識に至りにくいため、厄災は繰り返される。かくして、作り替えが困難なDB構造を抱えた九龍城のようなシステムが増えてゆく。

 DB設計は本来、システム設計の中でもとくに困難かつ責任重大な作業である。たしかにシステムのデータ要件や高層ビルの強度要件は、長い目で見れば変わることもある。だからこそエンジニアに期待されているのは、長期的に安定かつ堅牢な基本構造を創造することだ。けっして簡単な仕事ではない。とくに若手の技術者は、IDリクワイアドの甘い罠を避けつつ、関数従属性や定義域制約といったオーソドックスな知識を含むDB設計のスキルをじっくり身につけてほしい。なにしろいったんIDリクワイアドの癖がつくと、まず矯正できなくなるからだ。

 

*1.私自身、新人時代にそのようなDB設計に苦労させられた。先輩に「この主キーではレコードがユニークにならない可能性があるのですが」と尋ねると、「では、こちらの項目も主キーに含めてみて」と指示されたものだ。当時はそんなものかと従っていたが、今考えるとひどい話である。