J'ai une question sur la façon d'optimiser une requête. En fait, comme je vais lancer la requête fréquemment, je pensais utiliser une vue matérialisée ou indexée (est-ce une bonne idée ici?) Ou dénormaliser.Optimisation de requête/base de données: comment optimiser ceci? (et devrais-je utiliser une vue matérialisée?)
Considérons les quatre tableaux ci-dessous (avec des champs non pertinents omis):
- utilisateurs (int userId)
- Groupes (int groupId)
- GroupMemberships (int userId, int groupId, bool isSharing)
- ordinateurs (int userid)
Les relations sont qu'un utilisateur peut avoir 0..n ordinateurs (un utilisateur à l'homme y ordinateurs) et peut être membre de 0..n groupes. Un groupe peut avoir 0..n utilisateurs (de nombreux utilisateurs à plusieurs groupes). Le "isSharing" indique si un utilisateur partage avec ce groupe ou est un membre "en lecture seule" de ce groupe (c'est-à-dire, peut voir le partage des ordinateurs des membres, mais ne partage pas le sien).
La requête consiste à trouver, pour un utilisateur donné, les ordinateurs que cet utilisateur peut voir. Un utilisateur peut voir tous ses propres ordinateurs. Elle peut également voir tous les ordinateurs d'autres utilisateurs appartenant à des groupes dont elle est membre et qui partagent ce groupe. D'accord, cela ne fait pas beaucoup de sens, voici donc l'objectif en O (n^3) psudocode:
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
En ce moment je suis en utilisant un mappeur ORM et de faire essentiellement ce qui précède (je ne suis pas trop bon sur l'ensemble de la chose SQL), mais c'est évidemment une solution moins qu'idéale. J'ai des index sur tous les champs que j'ai listés ici (sauf isShared) et un index supplémentaire sur le tuple GroupMembership (userId, groupId). Mais les assistants de base de données peuvent-ils penser à une meilleure solution? Le projet n'est pas encore en ligne, mais je suppose qu'il y aurait en moyenne 1,2 ordinateur par utilisateur (tout le monde en aura un, quelques-uns en auront peut-être plus) et peut-être 0,75 appartenance à un groupe par utilisateur t utiliser la fonction de groupe, mais ceux qui le feront seront probablement membres de plusieurs groupes). En outre, toutes ces tables associées recevront des ajouts fréquents, ce qui peut rendre les vues matérialisées une solution moins pratique. J'utilise SQL Server 2008.
Merci, Bonne chance, Robert
Ah, merci, ça ressemble à ce que je fais en ce moment avec ORM ... mais avec deux sous-requêtes, cette requête sera-t-elle efficace? Et vaut-il la peine d'en faire une vision matérialisée? –
Oui, il n'y a qu'un seul utilisateur par ordinateur, mais peut-être plusieurs ordinateurs par utilisateur; Merci! –
La sous-requête n'est pas nécessaire, vous pouvez le modifier, mais c'est comme ça que je l'ai tapé en lisant votre question X-). Si l'indexation sur les tables est bonne, je ne pense pas que vous aurez trop de problèmes. En outre, vous voudrez probablement utiliser une fonction de requête ou de table en utilisant le param. De même, si les valeurs ne changent pas régulièrement, sans mettre en cache les valeurs, vous pouvez même ajouter un champ supplémentaire à la sélection, indiquant si l'ordinateur est direct ou partagé par un autre. La mise en cache des valeurs peut rendre les choses beaucoup plus rapides, mais n'oubliez pas d'effacer le cache lors des mises à jour, des suppressions et des insertions –