やる気がストロングZERO

やる気のストロングスタイル

やっぱり正規化をベースにしたテーブル設計しか勝たん

テーブル設計は正規化を基本にして設計する手法しか成功しない気がしてる。

DBやテーブル設計系の書籍を読むとどれにも「正規化」による設計手法が書かれているけど、現場ではなぜかあまり正規化に重きをおいた設計が行われていない場合が多かった。

先人の経験から「教科書通りにいけば理想的だが、現実はなかなかそうは行かない」という事なのかと思っていたが、結局はどれもあまりうまくはいっていないように見えた。

個人プロジェクトは正規化をベースに設計したテーブルで開発を行っているが、とてもうまくいっている。 テーブル設計はやはり正規化を基本にして行うべきだと、改めて思ったので書いてみる。

正規化とは?

テーブルからデータの重複を排除し整合性を保持してデータを扱えるようにするための手法。
DBとかテーブル設計の本を読むと書いてある。
情報処理の試験にも登場する。

正規化を使わない設計手法とは?

以下のようなもの。

エクセル表現がそのままテーブルとして定義されている

カレンダー表示をするためのテーブルでカラムに1,2,3,...,30,31というbool型が定義されてて、、みたいなテーブルを見たことがある。

カレンダー表現で作成されたエクセルを取り込む際その形のまま取り込んだ形。 カレンダー表示以外の機能には全く使えないデータになってる。

読み込む際に正規化した、適したテーブル構造にして入れておけば、カレンダー表示だけでなく、色んな要求に使えるデータになってたはず。

データ取得・保存がシンプルになるようにテーブル分割を避ける

テーブルが一つだと取得・保存が簡単だという考え方。

確かにテーブルが分割されていると、データの取得・保存は1テーブルに対して行うものよりも多少複雑になる。

しかし、コード側のアーキテクチャ設計を適切に行えば、複数テーブルになってもデータ取得の部分だけが意識すればいいだけで(むしろコアロジックはテーブルレコードを意識してはならない)そこまで大変にはならない。
データ整合性をつねに意識せねばならないデメリットのほうが遥かに大きい。

1テーブルにデータがまとまっていれば、データ内容の把握がしやすい

joinクエリを用意しなくてもデータの意味が見てわかりやすいという考え方。 確かにそうだけれども、表示のためにデータ整合性を犠牲にするのはメリデメのバランスがあってない。 見やすい表示が必要であればviewを用意するなどの方法もある。

そして、だいたいこういうテーブルは様々な暗黙条件が入り込むので一見は一覧できていてもそういった条件を加味してみないといけないため、思ったほど見やすくならない。

コード(ロジック)側の都合に合わせる

「この処理はこのテーブルデータを取得しているから、ここにデータがあると実装が楽」みたいなやつ。
その処理にとっては楽だったかもしれないが、別の処理からそのデータが必要になったときにものすごく取り辛かったりする。 どこにあれば便利か?ではなく、どこにあるべきか?で考えないとだめ。

パフォーマンスを心配する

  • 毎度集計しなくても良いように集計値を持ち回る
  • joinさせなくてもデータを取れるように持たせる

みたいなやつ。 データ不整合が発生する。

テーブル設計とパフォーマンスチューニングは別途考えるべきと思ってる。 パフォーマンスが必要な部分ではキャッシュを検討する。パフォーマンスのためにあるべきデータ構造を捻じ曲げると歪みが生じて苦しくなる。

まとめ:不整合が発生するようなテーブル設計をするとずっと苦しむことになる

正規化を無視したテーブル設計をするとデータ不整合が入り込む余地がたくさんできる。 不整合がおこるとバグになるので不整合を起こしてはいけないが、仕組みでカバーできないのでずっとこっち(プログラマー等の人)が不整合が起きないように面倒をみないといけない。

新しくjoinした人はこの事情を全て把握しないといけないがテーブル定義やコードからは読み取れない。暗黙のルール化する。

また、こういう「今見えている要件だけに最適化」していくようなテーブル設計は、その時見えている事情でしか設計されていないから、後日新たに発生した要件などに柔軟に対応できない。 結局、ロジック側と絡んだフラグカラムなどを駆使して歪んだテーブルに育っていってしまう。
シンプルに思えたテーブルはいつしかフラグだらけ、暗黙知だらけのテーブルになってしまう。