「このアプリケーションのこの機能は【年月日】までしか意識しない。【時分秒】はデータとして不要なのでテーブルにはdate型で【年月日】だけ持たせれば良い。」
と言われた事があったが例えアプリケーションにとって不要でもDBテーブルにはdatetimeとかtimestampで【時分秒】まで保持しておくべきだと思ったので書く。
DBはアプリケーション要件を意識しないほうがいい
アプリケーションを意識しまくったテーブル設計はアプリケーション要件に依存してしまう。
だからアプリケーション要件が変わるとテーブル設計を変更しないといけなくなる。
この時、既存データとの整合性をとる必要性まで出てきて大変になる。
逆にアプリケーションを意識していないテーブル設計は、アプリケーション要件が変わってもテーブル設計は変わらずにすむ。(新しくデータが必要な場合はもちろん新規にテーブル追加等は必要になるが。)
状況例
【時分秒】を持たなかった場合
- アプリケーションがユーザー登録日しか意識しないのでテーブルに時間は持たなかった。
- ある時「ユーザー登録先着100名に対してポイントプレゼントキャンペーン」なる機能の実装が必要になったが、時間を記録していないので同日登録の場合どちらが早いか判断できない(実際はid順で判別する手段に逃げると思うけど、idはUUIDを採用していたということにします)
- 時間まで持つようにテーブル定義を変更したが、過去の登録者に関しては0時0分0秒に登録したことになってしまった(事実とは異なるデータになってしまった。統計用データの集計時などにノイズになる)
【時分秒】を持っていた場合
- アプリケーションはユーザー登録日しか意識しないが、テーブルには登録時間までdatetimeやtimestampで持つようにし、アプリケーション側で日までしか使わないような感じで実装した。
- ある時「登録先着100名に対してポイントプレゼントキャンペーン」なる機能の実装が必要になったが、すでに時間までとっているので特に機能改修は不要だった。キャンペーン期間締め切り後、クエリで先着100名を選出できた。
まとめ
アプリケーション要件は変化しやすい。
アプリケーション要件に合わせたDBテーブル設計は、要件が変化したときに影響を受けてしまう。
テーブルは淡々と事実を記録するようにする。それをアプリケーションがどのように使うかは自由というスタンスを取るのが良い。(apiがアプリケーション要件を意識せず作られるのと同じ感じ。「使う側」「使われる側」という観点を持つ)
(補足)実際に【年月日】しかないデータはどう扱うか?
例えば外部から「2021-01-20」のような【時分秒】を持たないデータが入力されてテーブルに保持する場合はdate型で持たせれば良いと思う。