Performances très lentes sur SUM SQL Server 2008

J'ai une table de goûts / dégoûts qui contient environ 5 millions de lignes. Lorsque j'utilise la requête suivante pour get datatables, il se termine en 2+ minutes. Y a-t-il une meilleure approche de la façon dont je stocke et récupère les goûts / dégoûts? Chaque fois que quelqu'un aime / n'aime pas un article, il ajoute une colonne à la database. 0 Pour ne pas aimer et 1 pour comme. J'ai ensuite besoin de la sum des deux colonnes pour chaque user, puis renvoyer les users avec le plus grand nombre de goûts contre dégoûts. Si j'enlève les SUM pour les goûts / dégoûts, la requête returnne dans 4 secondes. J'ai aussi des index sur UserID et tout ce que je regroupe. Voici la requête:

SELECT TOP 50 Flows_Users.UserName, Flows_Users.UserID,Flows_Users.ImageName, Flows_Users.DisplayName, Flows_UserBios.bio, FlowsCount = (SELECT Count(1) FROM Flows_Flows WHERE UserID = Flows_Users.UserID AND Flows_Flows.Active = '1'), BeatsCount = (SELECT Count(1) FROM Flows_Beats WHERE UserName_ID = Flows_Users.UserID AND Flows_Beats.Active = '1'), FollowersCount = (SELECT Count(1) FROM Flows_Follow WHERE FOLLOWING = Flows_Users.UserID), FollowingCount = (SELECT Count(1) FROM Flows_Follow WHERE FOLLOWER = Flows_Users.UserID), ISNULL(SUM(Flows_Flows_Likes_Dislikes.[Like]) , 0) AS Likes, ISNULL(SUM(Flows_Flows_Likes_Dislikes.Dislike), 0) AS DisLikes FROM Flows_Users INNER JOIN Flows_Flows ON Flows_Users.UserID = Flows_Flows.UserID INNER JOIN Flows_UserBios ON Flows_Users.UserID = Flows_UserBios.userid INNER JOIN Flows_Flows_Likes_Dislikes ON Flows_Flows.FlowID = Flows_Flows_Likes_Dislikes.FlowID WHERE Flows_Users.UserID = Flows_Users.UserID GROUP BY Flows_Users.UserID, Flows_Users.UserName, Flows_Users.ImagePath, Flows_Users.ImageName, Flows_Users.DisplayName, Flows_UserBios.bio ORDER BY [Likes] DESC, [Dislikes] ASC, FlowsCount DESC 

Ce n'est pas une bonne idée de join une table de 5 millions de lignes. Si vous jetez un oeil au plan d'exécution, je parie que vous findez cette jointure entre Flows et Likes_Dislikes hashjoin – ce qui est le pire des cas.

La première étape de l'optimization de cette requête consiste à détecter quelle jointure ajoute du time à l'exécution. Supposément, il y a une partie de cette requête qui s'exécute dans un time acceptable (par exemple 1-2 secondes). Tout le rest est le problème. Et les problèmes sont résolus en dénormalisant les tables. Au lieu de se joindre à la table J'aime / N'aime pas, ajoutez la colonne de scores J'aime / Je n'aime pas dans la table Flux. À chaque fois que vous insérez dans des favoris / dégoûts, mettez immédiatement à jour l'logging de stream. En faisant cela, vous n'aurez pas besoin de la jointure lourde dans cette requête.

Gardez à l'esprit que la normalisation est une théorie bien définie, mais cette pratique va souvent à l'encontre de cette théorie. Trouver le bon équilibre entre les tables normalisées et la redondance fait du bon logiciel.