概要
利用可能端末を保持する際に、子テーブルを用意して、利用可能端末分だけ親テーブルに紐づくレコードを子テーブルに登録すると、検索時の結合コストが上がって嫌だったので、1カラムで管理できるようにしました
利点
- 結合する必要がないので、SQL のコストが下がる
- 1テーブルで管理できるので、登録/更新時のトランザクション制御が不要になる
方法
1. 管理したい端末種別分のビットカラムを用意する
ex.) 8種類なら BIT(8)
型のカラム
OR マッパーによっては BIT
型をサポートしていないことがあるので、カラムのバイト数は増えますが SMALLINT
型などを採用するのが良いと思います
2. 各ビットに端末種別を割り振る
各ビットに端末種別を割り振り、そのビットが 1
なら利用可能、0
なら利用不可能として運用する
ex.) 最下位のビットに PC を割り振る場合、00000001
なら PC 利用可能
実装
具体的にどう使用するかを書いていきます
1. テーブル定義
CREATE TABLE A (
-- 省略
device_type SMALLINT NOT NULL
);
端末は次のように割り振るとします
- 00000000 00000001
→ PC
- 00000000 00000010
→ MOBILE
- 00000000 00000100
→ SENYOU
2. 検索
検索条件に使用可能端末を0から複数件指定する場合、次の SQL で検索します
SELECT * FROM A WHERE device_type & $1 > 0
この $1 には検索したい端末種別のビットORを渡します
ex.) PC
と MOBILE
のどちらかが使用できるものを検索する場合
00000000 00000001
と 00000000 00000010
をビットORした値
00000000 00000011
つまり10進数の 3 を $1
に渡します
もしレコードの device_type
の値が 00000000 00000001
なら
device_type & 3
は 00000000 000001
になり
device_type & $1 > 0
が真になります
3. 登録
検索の逆で、使用可能端末のビットORを登録します
ex.) PC
と SENYOU
を利用可能として登録したい場合
00000000 00000001
| 00000000 00000100
=> 00000000 00000101
つまり 5 を登録すれば良い
おわりに
一見分かりにくいですが、管理するテーブルが増えず、バイト数も最小限に抑えられ、SQL のコストも下がるので個人的には好きです。
ただ、この方法で管理しているのを見たことがなく、バッドプラクティスなのかもしれないので、詳しい方がいたらご教授ください