Blog
本記事の目的
論理設計のアンチパターンについて学びます。
ネットや書籍から得た知識や、自身の経験を通じて「これは避けるべき」というパターンをいくつか紹介します。
① 非スカラ値
以前、正規化の記事で紹介しておりますが、要するに第一正規形に違反している状態のことを指します。
この状態では、データの検索や更新が非常に不便になり、避けるべきパターンとして広く認識されています。
ただし、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
あくまでも本業がメインですが、休日や業務の隙間時間は個人でも動いております。
もしお手伝いできることがあれば、お気軽にお問い合わせください。