J'ai un SQL Server 2008 CTE chargé de renvoyer le Top Review pour un emplacement. Le CTE est enveloppé dans un champ UDF (Table-Valued), et joint sur le champ LocationId, donc je peux obtenir la meilleure évaluation pour chaque emplacement.Aide pour améliorer les performances de SQL Server 2008 CTE
Cardinalités:
Lieu a 0- beaucoup PostLocations
PostLocation a Poster
Post dispose critique
est ici l'UDF:
CREATE FUNCTION [dbo].[Review_HighestRated_Aggregated_ByLocation]
(
)
RETURNS TABLE
AS
RETURN
(
WITH [RankedLocations] AS
(
SELECT PL.LocationId,
R.Rating,
P.PostID,
P.UniqueUri,
P.Content,
ROW_NUMBER() OVER (PARTITION BY PL.LocationId ORDER BY R.Rating DESC, P.LocationTypeId, P.CreatedOn DESC) As ScoreRank
From dbo.PostLocations As PL
INNER JOIN dbo.Posts As P
ON P.PostId = PL.PostId
INNER JOIN dbo.Reviews As R
ON R.PostId = P.PostId
WHERE R.ReviewTypeId <> 5
AND P.Content IS NOT NULL
)
SELECT LocationId, Rating, PostID, UniqueUri, Content
FROM RankedLocations
WHERE ScoreRank = 1
)
Voici un exemple de la façon dont je l'utilise:
select l.LocationId, l.Name, l.UniqueUri, r.UniqueUri, r.Content
from @Locations l -- temp table containing around 18 location ids
inner join dbo.Review_HighestRated_Aggregated_ByLocation() r
on l.LocationId = r.LocationId
La requête ci-dessus prend 15 secondes à exécuter, ce qui est inacceptable. Sans la jointure à l'UDF cela prend 0 secondes.
Des idées sur comment je peux l'améliorer? Si je regarde le plan d'exécution, c'est le SORT qui prend 98% du coût d'exécution. Le coût IO/sous-arbre de cette opération est ~ 300. J'espérais que le plan d'exécution me donnerait un indice sur un indice que je pourrais créer pour améliorer le coût, mais je n'obtiens rien.
Des idées?
Existe-t-il un index sur 'R.ReviewTypeId' ?? Avez-vous des indices sur les colonnes utilisées pour les relations de clés étrangères ('PostId' dans les trois tableaux)? Aussi: une autre option serait d'essayer d'utiliser directement le CTE dans votre requête, au lieu de le "cacher" à l'intérieur de l'UDF (ce qui peut être notoirement lent ...) - cela fait-il une différence? –
@marc_s. Oui, il existe un index sur ReviewTypeId. Oui, PostId est un PK groupé sur Posts, une partie de PK en cluster sur PostLocations, et PK en cluster sur Reviews. J'ai aussi essayé d'utiliser le CTE directement, pas de changement. J'ai essayé de créer une vue, ce qui est bien, mais vous ne pouvez pas indexer une vue qui contient des opérations agrégées ou des sous-requêtes. En ce moment je penche vers une "table de cache" qui est mise à jour toutes les heures avec un travail planifié de sql. pensées? – RPM1984