🔥

ORM のポリモーフィック関連は使うべきか?

2024/01/28に公開

データベースにおけるポリモーフィックは、子テーブルが複数ある親テーブルのうちどれか 1 つと関連することです。

この記事では、 imagesusersposts のどちらかを親テーブルとして持つポリモーフィック関連を例に話を進めていきます。

データベースから見た問題点

ポリモーフィックの 1 番の問題としてテーブル間の関連がなくなることが挙げられます。これは外部キーを設定することができないからです。
外部キーは 2 つのテーブルを関連づけるキーですが、ポリモーフィックの子テーブルでは、行ごとに関連づけられる親テーブルが変わるために外部キーを一意に設定できません。

これにより以下の問題が発生します。

参照整合性がなくなる

外部キーを設定できないので、データベース上では参照整合性を保証できません。
そのためアプリケーションコードで制御する必要があります。

参照整合性

関連づけられているテーブル間のデータが一貫していること。
データベースでは外部キー制約で参照整合性を保証しています。

移植性が悪くなる

ポリモーフィックを使うとアプリケーションコードとデータベースが密結合になります。
これは本来データベースの役割であるテーブル間の関連をアプリケーションコードで制御していることにあります。これによりデータベースがアプリケーションコードに依存し、データベースのみを移植することが難しくなります。

クエリが複雑になる

ポリモーフィックを利用すると結合時に親テーブルを指定する必要があります。

  • user に紐づく画像を取得するクエリ
SELECT *
FROM users AS u
INNER JOIN images AS i
ON u.id = i.resource_id AND i.resource_type = 'user'
  • 全ての画像と紐づく親レコードを取得するクエリ
    紐づく親テーブルごとに左外部結合が必要
SELECT *
FROM images AS i
LEFT OUTER JOIN users AS u
ON u.id = i.resource_id AND i.resource_type = 'user'
LEFT OUTER JOIN posts AS p
ON p.id = i.resource_id AND i.resource_type = 'posts';

ORM でポリモーフィックを使う利点

ポリモーフィックの利点はコードのシンプルさと柔軟性にあります。

シンプルで柔軟

ポリモーフィックはテーブル間の関連をアプリケーションコードで実現することで柔軟性をもたらします。
さらに ORM を使えば参照整合性などの複雑なロジックは、カプセル化されるため Ruby On Rails の ActiveRecord ではたった 1 行でデータベースを変更せずとも子テーブルと関連付けができます。

has_many :images, as: :resource

個人的見解

ポリモーフィックは、短期的な開発スピードとデータベース構造の複雑化のトレードオフを伴います。

ポリモーフィックの柔軟性

ポリモーフィック関連の柔軟性は一見魅力的ですが、同様の柔軟性はデータベースの設計で実現可能です。以下のように中間テーブルを介して親テーブルと子テーブルを関連づけることで、後から新しい親テーブルを追加する事が可能です。

結論

ポリモーフィックを使用することで短期的な開発スピードは向上しますが、その代償としてデータベース構造が複雑化します。データベースの複雑性は、プロジェクト全体の見通しを悪くして、かえって生産性やスピード感を低下させます。

長期的なプロジェクトの継続と拡張を考えた時にデータベース構造を複雑化させたくなので ORM のポリモーフィック関連は採用すべきではないと考えました。

参考

UKIYOcreate

Discussion