SQLアンチパターン 第5章を読んで
を読んでの要約、感想です。
目的
同じ属性を持ちつつも、例えばSmartphoneというオブジェクトがあるとして方やandroid_version、方やios_versionを持っている場合に対応したいというのが今回の目的です。
アンチパターン
別テーブルをつくり属性を行に格納してしまうというものです
smartphone_id | os_version | os_version_value(VARCHAR) |
---|---|---|
1 | android_version | oreo |
2 | ios_version | 12 |
3 | blackberry_version | 7.1 |
いちいちSmartphonesテーブルに列を増やさなてくてもいいですし、急なOSの登場にも耐えられます。
デメリット
- 対象の行を指定してから取り出すして使う必要がある。(これは織り込み済みのデメリットの気もしますが)
- 行に属性がはいるのでデータ型なんかは整合性はとれず文字列をいれるしかありません。もしくはデータ型に対応するカラムをたくさん用意するかです。
- 行として属性をもっているので内部結合しようと持っていない属性を指定してしまうと結合できず、何も取り出せないので外部結合するしかありません。必然的に扱う行の数は多くなります。
使用してもいい場
SQL以外の非リレーショナルな技術をつかう時とあります。確かに。
解決策
- シングルテーブル継承
サブタイプの数が限られていれば
smartphone_id | name | os | android_version | ios_version |
---|---|---|---|---|
1 | iphone6 | ios | oreo | null |
2 | honor9 | android | null | 12 |
ActiveRecordを使うような単純な設計の時◯です。
- 具象テーブル継承
変化する属性ごとにテーブルをつくります。
smartphone_id | name | os | ios_version |
---|---|---|---|
1 | iphone6 | ios | 12 |
smartphone_id | name | os | android_version |
---|---|---|---|
2 | honor9 | android | oreo |
nullがなくなります
- クラステーブル継承
smartphone_id | ios_version |
---|---|
1 | 12 |
smartphone_id | android_version |
---|---|
2 | oreo |
共通要素を元テーブルで持ち、違う要素をそれぞれ別のテーブルに切り出すというものです。その名の通りクラス継承と同じ形です。
- 半構造化データ
smartphone_id | name | os | version_attributes |
---|---|---|---|
1 | iphone6 | ios | android_version: oreo |
2 | honor9 | android | ios_version: 12 |
LOB列を作りそこにJSON等の形式で格納してしまおうというものです。SQLでアクセスできなくなるので流石に無理がある気がします。
感想
メタデータを格納させると大変だよという章だと思いました。現実的にはシングルテーブル継承が一番使いやすいかなと思います。