クエリを最適化する方法について質問があります。実際、クエリを頻繁に実行する予定なので、具体化されたビューまたはインデックス付きビューを使用するか (これは良い考えですか?)、非正規化することを考えていました。
次の 4 つのテーブルを考えてみましょう (無関係なフィールドは省略されています)。
- ユーザー (int userId)
- グループ (int groupId)
- GroupMemberships (int userId、int groupId、bool isSharing)
- コンピュータ (int userId)
この関係は、ユーザーが 0..n 台のコンピューター (1 人のユーザーから多数のコンピューター) を持つことができ、0..n グループのメンバーになることができるということです。グループには 0..n 人のユーザー (多数のユーザーから多数のグループ) を含めることができます。「isSharing」は、ユーザーがそのグループと共有しているか、そのグループの「読み取り専用」メンバーであるかを示します (つまり、共有メンバーのコンピューターを表示できますが、自分のコンピューターは共有しません)。
クエリは、特定のユーザーについて、そのユーザーが表示できるコンピューターを見つけることです。ユーザーは、自分のすべてのコンピューターを表示できます。彼女はまた、彼女がメンバーであり、そのグループと共有しているグループに属している他のユーザーのコンピューターも見ることができます。さて、それはあまり意味がないので、O(n^3) 疑似コードの目標は次のとおりです。
List<Computer> l
foreach(Computer c in Computers)
if(c.userId == current_user_id)
add c to l
else
foreach(GroupMembership m where m.userId == current_user_id)
foreach(GroupMembership m2 where c.userId == m2.userId && m.groupId == m2.groupId)
if(m2.isSharing)
add c to l
現在、私は ORM マッパーを使用しており、基本的に上記のことを行っています (SQL のことはあまり得意ではありません) が、それは明らかに理想的とは言えない解決策です。そこにリストしたすべてのフィールド (isShared を除く) にインデックスがあり、GroupMembership の (userId, groupId) タプルに追加のインデックスがあります。しかし、データベースの専門家がより良い解決策を思い付くことができるでしょうか?
プロジェクトはまだ稼働していませんが、ユーザーあたり平均 1.2 台のコンピューター (全員が 1 台、一部はそれ以上のコンピューターを所有する可能性があります) であり、ユーザーあたりのグループ メンバーシップはおそらく 0.75 になると思います (多くのユーザーはグループを使用しません)。機能ですが、そうする人は複数のグループのメンバーになる可能性があります)。また、これらの関連付けられたテーブルはすべて頻繁に追加されるため、マテリアライズド ビューの実用性が低下する可能性があります。SQL Server 2008 を使用しています。
ありがとう、万歳、ロバート