Blog

論理設計⑤ やってはいけないアンチパターン

2024.12.24

本記事の目的


論理設計のアンチパターンについて学びます。
ネットや書籍から得た知識や、自身の経験を通じて「これは避けるべき」というパターンをいくつか紹介します。


① 非スカラ値


以前、正規化の記事で紹介しておりますが、要するに第一正規形に違反している状態のことを指します。
この状態では、データの検索や更新が非常に不便になり、避けるべきパターンとして広く認識されています。


ただし、SQLには「配列型」というデータ型が存在します。
これはリレーショナルデータベースの原則である「スカラ値のみを扱う」というポリシーに反しており、「非スカラ」を許容するものです。
しかし、この「配列型」を利用する場合、アプリケーションやミドルウェア側での対応が必要となり、それに伴うコストが発生します。
そのため、現時点ではあまり普及していないようです。


テーブルを増やすのは手間だし、結局いろいろな種類のデータを持たせるわけでもないから「配列型で済ませよう」という発想は、後々痛い目を見る可能性が高いですね。
やはり、より柔軟に対応できるテーブル設計を目指し、正規化をしっかり行う方が良いと思います。


② 単一参照テーブル


これはこれまでに何度も目にしてきた設計です。
テーブル数が少なく、一見するとシンプルに見えますが、実際に実装する際には少し面倒だと感じることが多いです。


同じ構造のマスタデータを一つのテーブルにまとめちゃおうっていう手法になります。


色マスタ



























id code name
1 red
2 blue
3 green

性格マスタ



























id code name
1 kind 優しい
2 brave 勇敢な
3 shy 内気な


単一参照マスタ

















































id type code name
1 color red
2 color blue
3 color green
4 personality kind 優しい
5 personality brave 勇敢な
6 personality shy 内気な

と、こんな感じで一個のマスタにまとめちゃうことを言います。


可読性の低下


テーブルが単一化されることで、参照先のデータが増えるにつれて、その内容を把握するのが難しくなります。
たとえば、「コード」や「名前」といった汎用的なカラム名では、何を指しているのかが分かりにくくなることがあります。


データの整合性の問題


複数の異なる種類のデータが同じテーブルに格納されると、誤ったデータが登録されるリスクが高まります。
たとえば、「顧客区分」と「商品カテゴリー」を同じ参照テーブルで管理する場合、間違った組み合わせが登録される可能性があります。


クエリの複雑化


データの種類ごとに条件を設定する必要が出てくるため、SQLクエリが複雑になりがちです。
また、ジョインや条件分岐の処理が増えるため、パフォーマンスにも影響を与えることがあります。


こうした理由から、単一参照テーブルは一見便利そうに思えても、長期的には非効率になりがちです。
やはり、用途ごとに適切な参照テーブルを分ける方が、設計や実装の面でメリットが大きいと言えるでしょう。


③ 不適切なindexの付与


indexの効果を正しく発揮させるためには、適切なカラムにindexを付与することが大切です。



  • カーディナリティの高いカラム

  • JOINやWHERE句で頻繁に利用されるカラム

  • 更新が少ないカラム


このように、適切なカラムを選ばずにやみくもにインデックスを付与する(インデックスショットガン)と、
更新時のパフォーマンスが低下し、ストレージを無駄に消費してしまいます。


④ とりあえず論理削除(グレーパターン?)


私はLaravelで開発する機会が多く、Eloquentモデルでトレイトを使うことで、Laravelでは論理削除の実装が比較的簡単に行えます。
ただ、本当に論理削除でいいのか?という場面によく遭遇します。なぜなら、個人的には以下のデメリットを感じているからです。


レコードが肥大化しがち


論理削除済みのデータもレコードとして残るため、テーブルが肥大化します。
これにより、検索やクエリ実行時のパフォーマンスが低下する可能性があります。特に大量のデータが蓄積されるシステムでは、論理削除されたレコードが不要な負荷をかける原因となります。


ユニークキー貼る時に面倒


論理削除ではレコードが残るため、ユニーク制約が十分に機能しないことがあります。
例えば、メールアドレスにユニーク制約を貼ることは一般的に良い方法ですが、論理削除を行った後に同じメールアドレスで新たにデータを登録しようとすると、ユニーク制約によってエラーが発生してしまいます。この問題を解決するためには、別途カラムを追加して対策を講じる必要があり、少し手間がかかります。


外部キー制約が無効になる


論理削除の場合、レコードは物理的に削除されず、削除フラグが立てられるだけです。このため、外部キー制約を設定している場合、削除されたデータが依然として存在し、リレーションを持つテーブルで整合性を保つことが難しくなります。


例えば、親レコードが論理削除されても、子レコードがその親レコードを参照している場合、外部キー制約に引っかからないため、リレーションが壊れることがあります。これに対処するには、親レコードが論理削除された場合、関連する子レコードも一緒に論理削除するか、別の方法で整合性を取る必要があります。
※ON DELETE CASCADEも物理削除しか拾えないですし


メリットもあるよ



  • 誤削除リスクの軽減

  • 履歴情報としての活用


などのデータの安全面には大きなメリットがあります。
ただし、これらのデメリットを考慮せずに「とりあえず論理削除」を選択すると、後々問題が発生する可能性があります。プロジェクトの特性やこれらのメリット・デメリットを十分に考慮した上で、適切な選択をすることが重要だと思います。


終わり


まだまだ様々なアンチパターンがありますが、比較的よく見るアンチパターンについて紹介しました。
さまざまな手法がある中で、そのプロジェクトに最適な手法を選ぶには、やはり基本的な知識がしっかりしていないと、
アンチパターンに陥ってしまうと感じながら執筆していました。


これからも思考を止めず、視野を広く設計できたらと思っています。
それでは、ここまでお付き合いいただきありがとうございました:)


CONTACT

あくまでも本業がメインですが、休日や業務の隙間時間は個人でも動いております。
もしお手伝いできることがあれば、お気軽にお問い合わせください。

SNS