設計者の発言

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

更新履歴と更新予約を「時限属性」で合理化する

 マスター系テーブルの主キーにいちいち「適用開始日」や「履歴番号」が含まれているDB設計を見たことはないだろうか。品目マスターを例にすると主キーが{品目№}ではなく、{品目№+適用開始日}とか{品目№+履歴番号}のようになっていたりする。このように設計した場合、他テーブルとの間に成立しているはずの豊かな関係が見えなくなる(図1)。結果的に、システム仕様の可読性や保守性が著しく低下する。

図1.適用開始日を主キーに含むとテーブル関連が見えない

 ここでは「適用開始日」が主キーに含まれるケースを前提にして話を進めよう。この奇妙な設計方針を採用しているユーザ企業に話を聞く機会があったのだが、それなりの理由が2つあることがわかった。そのシステムがマルチテナント方式で顧客に提供しているサービスにおいて、各顧客が定義したマスターの更新履歴を保持することが求められているため。もうひとつは、それらのマスター値が規定期日において自動的に切り替わることが求められているためだ。たしかに、適用開始日を主キーに含めることで、適用開始日が過去日付であればこれまでの更新履歴となるし、未来日付にすることで項目値の変化を「予約」できる。

 これらはテーブルの「更新履歴管理」および「更新予約管理」と呼ばれる課題なのだが、それにしてもこの設計方針は対応策として最善とは言い難い。上述したようにテーブル間の論理関係がわかりにくくなるし、マスターレコードを検索するためのSQLが恒常的に複雑化するからだ。

 このような場合に参考にしてほしいのが「時限属性」の考え方だ。時限属性とそうでない項目とを意識的に区別して別テーブルに配置する。そもそも時限属性とは何かを理解するためには、「時限属性でない項目」を説明するほうが早い。

 たとえば、品目の発効日や失効日(*1)といった属性項目を想像してほしいのだが、これらの更新履歴を管理する意義はうすい。事実上、最大値(永遠の未来。9999/12/31)に設定されている失効日を数カ月後の日付に変更する事態が1回だけ起こるのだが、大事なのは失効日がいつ変更されたかではなく、その品目がいつ失効するかだ。また、値を変更したくなったらその場で更新すれば済むので、更新予約の必要もない。

 他にもたとえば「在庫管理区分(在庫管理品かどうかを表す)」や「扱い単位区分(計数単位のこと)」といった、品目としての基本的性質を表す項目の値が更新される事態は考えにくい。それらが変化するとしたら、既存品目の属性値の更新ではなく新たな品目が追加されたとみなすほうが自然だし、業務上も対応しやすい。

 つまり、ある種の項目は「更新履歴管理」や「更新予約管理」の対象にならないということだ。すなわち、それらの項目は値の変化が時間的に管理されるべき「時限属性」ではない。これらを除いた他の項目群を時限属性とみなして、{品目№+適用開始日}の主キーを持つ別テーブル「品目別時限属性」に切り出してみよう(図2)。品目名は時限属性とは多少考えにくいが、ここではあえて切り出してみた。

図2.時限属性テーブルの例

 単純な工夫だが、DB構成の見通しが桁違いに良くなる。他テーブルとの論理関係や、どの項目を時限属性とみなしたかも明確だ。現時点で有効な時限属性を参照したい場合には複雑なSQLが必要になるが、与えられた品目№の値が存在しているか、あるいは現時点で有効かどうかを調べるだけなら単純なSQLで済む。そもそも時限属性にアクセスすることに意識的になれるので、複雑なSQLを書かねばならないとしてもそのコンテキストは明瞭である。

 大事なのは「すべての項目が時限属性というわけではないこと」、また、図2の倉庫のように、「すべてのテーブルが時限属性テーブルを伴う必要もないこと」に気づくことだ。こういった緻密な検討をしないまま、マスターテーブルの主キーに適用開始日や履歴番号を機械的に組み込むやり方は、あまりに思考停止的姿勢と言わざるを得ない。

 システム刷新において適切なデータモデルを導くためには、個々のテーブル、個々の項目の意味や位置づけを常に抜本的に考える姿勢が求められる。たとえそれが職場やコミュニティでの常識であったとしても、旧システムでの設計スタイルの合理性を疑う習慣を身につけてほしい。「今までこうやっていたから」なんて理由だけで納得してはいけない。

 

*1.発効日、失効日の代わりに「削除フラグ」を置くやり方はアンチパターンだ。「いつ削除フラグをオンにしたか」を履歴管理したくなるし、オンへの更新を許すための妥当性検査や更新後の扱い方針も複雑だからだ(大抵はまともに検討されない)。発効日、失効日で有効期間を規定するやり方であれば、「有効期間をはずれたマスター値が参照されることは許されるが、それを用いた新たな取引は禁止される」のシンプルな取扱方針で統一できる。物理削除の際の妥当性検査は「その主キー値を参照するテーブルレコードが1件でも存在している限り許されない」でふつうはOKだ。