0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

子テーブルを親テーブルの1カラムにして管理する

Last updated at Posted at 2024-12-12

概要

利用可能端末を保持する際に、子テーブルを用意して、利用可能端末分だけ親テーブルに紐づくレコードを子テーブルに登録すると、検索時の結合コストが上がって嫌だったので、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 00000001PC
 - 00000000 00000010MOBILE
 - 00000000 00000100SENYOU

2. 検索

検索条件に使用可能端末を0から複数件指定する場合、次の SQL で検索します

SELECT * FROM A WHERE device_type & $1 > 0

この $1 には検索したい端末種別のビットORを渡します
 ex.) PCMOBILE のどちらかが使用できるものを検索する場合
   00000000 0000000100000000 00000010 をビットORした値
   00000000 00000011 つまり10進数の 3 を $1 に渡します
   もしレコードの device_type の値が 00000000 00000001 なら
   device_type & 300000000 000001 になり
   device_type & $1 > 0 が真になります

3. 登録

検索の逆で、使用可能端末のビットORを登録します
 ex.) PCSENYOU を利用可能として登録したい場合
   00000000 00000001 | 00000000 00000100 => 00000000 00000101
   つまり 5 を登録すれば良い

おわりに

一見分かりにくいですが、管理するテーブルが増えず、バイト数も最小限に抑えられ、SQL のコストも下がるので個人的には好きです。
ただ、この方法で管理しているのを見たことがなく、バッドプラクティスなのかもしれないので、詳しい方がいたらご教授ください

0
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?