Tallman

技術とか読書とかいろいろ

SQLアンチパターン 第5章を読んで

SQLアンチパターンwww.oreilly.co.jp

を読んでの要約、感想です。

目的

同じ属性を持ちつつも、例えば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の登場にも耐えられます。

デメリット

  1. 対象の行を指定してから取り出すして使う必要がある。(これは織り込み済みのデメリットの気もしますが)
  2. 行に属性がはいるのでデータ型なんかは整合性はとれず文字列をいれるしかありません。もしくはデータ型に対応するカラムをたくさん用意するかです。
  3. 行として属性をもっているので内部結合しようと持っていない属性を指定してしまうと結合できず、何も取り出せないので外部結合するしかありません。必然的に扱う行の数は多くなります。

使用してもいい場

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でアクセスできなくなるので流石に無理がある気がします。

感想

メタデータを格納させると大変だよという章だと思いました。現実的にはシングルテーブル継承が一番使いやすいかなと思います。