私の Rails アプリケーションには、ユーザー データを含むさまざまなデータベース テーブルがあります。これらのテーブルの中には、多数の行 (場合によってはユーザーごとに 500,000 行) があり、頻繁にクエリが実行されます。テーブルに何らかのクエリを実行するたびに、現在のユーザーの user_id がクエリのどこかにあります。テーブルがユーザーと直接関係がある場合は直接、または他のテーブルを介して関係している場合は結合を介してです。
パフォーマンスを向上させるために、user_id を非正規化してすべてのテーブルに含める必要がありますか?
一例を次に示します。
- アドレスはユーザーに属し、user_id を持っています
- エンベロープはユーザーに属し、user_id を持っています
- AddressesEnvelopes は Address と Envelope を結合するため、envelope_id と address_id があります。user_id はありませんが、envelope または address (同じユーザーに属している必要があります) のいずれかを介してアクセスできます。
一般的な高価なクエリの 1 つは、特定のユーザーのすべての AddressesEnvelopes を選択することです。これは、Address または Envelope のいずれかと結合することで実現できますが、これらのテーブルからは何も必要としません。または、このテーブルでユーザー ID を複製することもできます。
別のシナリオを次に示します。
- レターはユーザーに属し、user_id を持っています
- 受信者は Letter に属し、letter_id を持っています
- RecipientOption は Recipient に属し、recipient_id を持っています
レターを介してアソシエーションを経由することでいつでもアクセスできますが、受信者と受信者オプションの両方で user_id を複製することは理にかなっていますか?
いくつかのメモ:
- ユーザー間で共有されるオブジェクトはありません。関連オブジェクトの階層全体は、常に同じユーザーに属します。
- オブジェクトのユーザー所有者が変わることはありません。
- データベースはデータ集約型のアプリケーションであるため、データベースのパフォーマンスは重要です。多くのクエリと多くのテーブルがあります。
では、インデックスを作成するときに使用できるように、すべてのテーブルに user_id を含める必要がありますか? それとも設計が悪いのでしょうか?