読者です 読者をやめる 読者になる 読者になる

valid,invalid

関心を持てる事柄について

リレーショナルデータベースでは履歴の管理をすべきでない?

リレーショナルデータベースで履歴の管理は難しい。


いまDB設計を担当している案件で、業務用件として履歴管理が現れた。
「データの更新の度に更新前後のデータを保持し、過去のある時点のデータを再現したい」という。

どう実装するか。。

追加のみ行うよう設計する

はじめに考えたのはテーブルAにはレコードの追加のみ行う、という方法。
しかし…下記の理由により断念。
  1. テーブルAのオカレンスは頻繁に更新され、レコード数が大変なことになる。オンライン処理の為、厳しい。
  2. また、今回はテーブルAだけでなく、テーブルAとリレーションを持つ他の幾つかのテーブルの履歴も持たなければならない。つまり、テーブルAを更新する為に他の複数のテーブルにINSERTを行わなければならなくなってしまう。これをアプリケーション実装者に強いるのはリスク。

本体と履歴の情報を分ける

テーブルAとは別にテーブルA履歴を用意する方法。履歴テーブルにはテーブルAの主キーとリビジョンなどを持たせる。最新のデータを取得するにはテーブルAを見るだけで良いので問題1.は解決。

テーブルAの更新と同時にテーブルA履歴にINSERT。これも問題2.を孕んでいるが、テーブルUPDATE,INSERT,DELETE時に履歴系テーブルにINSERTするトリガーを作成することでやや改善する。データの追加・更新・削除は履歴を意識せず、本体に行えば良いのでアプリ実装負担にはならないはず。


ひとまずこんな感じで設計したが、未だ残る一番の懸念は履歴に対する検索処理。とにかく重そう。
集計表としてマテリアライズド・ビューの作成も検討しているが、検索条件の柔軟な変更に対応できるだろうか?また、対応コストは高くつかないだろうか?
もう少し、考えてみたい。

履歴とは


ちなみに【DOAコラム】-更新と履歴によると、履歴には3種類があるという。(詳細はリンク先参照)
1.単純に行為・出来事の事実を記録する履歴
2.元の行為・出来事が変更されるので、変更前の状態を記録する履歴
3.継続的な発生を前提にして、行為・出来事の事実を記録する履歴
今回の要件では2.に当たる。このうち1.と3.の実態はイベント(行為/出来事)の集積であって、イベントテーブルを作ってそこにレコードを追加していけばよいとのこと。

【参考】