本記事は、選択肢リストの保存方法について紹介します。
はじめに
選択肢リストとは、範囲や選択肢が限定された値のことです。例えば、"Active"・"Deleted" といったユーザーの会員状態や、"東京都"・"千葉県"など都道府県のことを指します。
本記事では、ユーザーの会員状態の保存を例に、選択肢リストの値をRDBに保存する複数の方法と、それぞれのメリット・デメリットについて紹介します。
1. マスタテーブルを作成する
データの厳密性が必要な場面で強みを発揮する方法です。 マスタテーブルとは、システムの運用上で必要な情報が格納されたテーブルのことです。今回の例では、会員状態のリストがこれにあたります。親テーブル側では、マスタテーブルの外部キーIDを保存します。
この方法のメリットは、データの厳密性を担保出来ることです。 外部キー制約を用いることにより、意図しない値の混入を防ぐことが出来ます。また、マスタテーブルにカラムを追加することで、追加情報を加えることも出来ます。都道府県の場合、関東・東北といった地域情報がこれにあたります。
一方、デメリットはパフォーマンス面で若干劣る点です。 この方法では、データ取得や保存をする際に親テーブルとマスタテーブルの両方を読み込む必要があります。また、絞り込みを行う場合、親テーブルとマスタテーブルを結合しなければなりません。親テーブルからマスタテーブルへの参照が増えていくと、段々とパフォーマンスが悪くなり、さらにアプリ側のコードも複雑になる可能性があります。
2. アプリ側で選択肢リストを定数化する
パフォーマンスを優先したい場面で、強みを発揮する手法です。 ymlや連想配列などを使用して、アプリ側に選択肢リストを定数として持たせるようにします。データベースに保存する際には、アプリ側で選択肢を数値に変換したものを保存します。
この方法のメリットは、パフォーマンスに優れることです。 データの保存や取得の際にデータベースへのアクセスが不要なため、先程の方法よりも高速です。
一方、デメリットは厳密性と変更のしにくさです。 外部キー制約が使えないため、データベースレベルで不正な値が入る可能性を許容してしまいます。また、複数のアプリで同じリストを使いたい場合、それぞれが別々に定数を管理しなければならず、変更の際は一貫性が崩れないよう注意しなければなりません。
3. 履歴テーブルを作成する
リストの変更履歴を記録したい場面で強みを発揮する手法です。 これまで紹介した1と2のどちらの方法も、状態の変更履歴を保存することは出来ませんでした。そこで、テーブル構造を行持ちにすることで、リストの値を変更するたびにレコードが作成されるようにします。
この方法のメリットは変更履歴を追跡出来ることです。 配送状態など、そもそもリスト値の遷移がアプリ側で必要な場合もありますし、他にもトラブルシューティングや統計取得の際にも、変更履歴は役に立つことがあります。
一方、デメリットは設計が複雑なこととパフォーマンスが悪いことです。 まず、この方法はテーブル数が多くなります。加えて、アプリ側で履歴テーブルを上手く取り扱うための処理が必要になります。また、レコード数が漸進的に増えていきますので、段々とパファーマンスも悪化していく傾向にあります。
4. カラムに直接値を保存する
簡単な反面、欠点も多い方法です。 選択肢リストの値を親テーブルに直接保存します。
この方法のメリットは、設計がシンプルなことです。 選択肢リスト用のテーブルを作成する必要がないため、テーブル数は最小限で済みます。また、保存される値が文字列なので見やすくはあります。
一方、デメリットは、柔軟性に欠けることです。 選択肢リストの値が変更された場合、関連する親テーブルのレコードを一括更新しなければなりません。また、カラムに制約が存在しないため、意図しない値が混入するリスクがあります。データベースによっては、Enum型やCheck制約などが使用出来ますが、SQLアンチパターンでもあるため扱いには注意が必要です。
まとめ
大切なのは、選択肢リストの用途に応じて適切な手法を選択することです。 どの方法にも何かしらのデメリットは存在します。ですので、何が必要で、何を犠牲にしてもいいのかを考えて設計手法を選択するようしましょう。