Question

J'ai une procédure stockée qui utilise une vue de tirer 6 moyennes. La base de données SQL est SQL Server 2000. Lorsque je le lance dans l'analyseur de requêtes, il faut environ 9 secondes. Que puis-je faire pour obtenir une meilleure performance? Dois-je retourner les lignes en utilisant LINQ et déterminer une moyenne de cette façon? Sera-ce plus rapide?

Voici un exemple de mon sproc actuel:

create procedure [TestAvg]
(
    @CustomerNumber int
)
as

select
(select AVG(OrderTime) from OrderDetails where ProductID = 12 and DateDiff(day, DateFulfilled, GetDate()) <= 7 and CustomerNumber = @CustomerNumber) as P12D7,
(select AVG(OrderTime) from OrderDetails where ProductID = 12 and DateDiff(day, DateFulfilled, GetDate()) <= 30 and CustomerNumber = @CustomerNumber) as P12D30,
(select AVG(OrderTime) from OrderDetails where ProductID = 12 and DateDiff(day, DateFulfilled, GetDate()) <= 90 and CustomerNumber = @CustomerNumber) as P12D90,
(select AVG(OrderTime) from OrderDetails where ProductID = 16 and DateDiff(day, DateFulfilled, GetDate()) <= 7 and CustomerNumber = @CustomerNumber) as P16D7,
(select AVG(OrderTime) from OrderDetails where ProductID = 16 and DateDiff(day, DateFulfilled, GetDate()) <= 30 and CustomerNumber = @CustomerNumber) as P16D30,
(select AVG(OrderTime) from OrderDetails where ProductID = 16 and DateDiff(day, DateFulfilled, GetDate()) <= 90 and CustomerNumber = @CustomerNumber) as P16D90

En outre, permettez-moi de préciser le point de vue mentionné ci-dessus. Comme il s'agit SQL Server 2000, je ne peux pas utiliser une vue indexée, car il utilise une sous-requête. Je suppose que cela peut être réécrite pour utiliser les jointures. Cependant, la dernière fois que nous avons pris une requête et récrit à avoir recours aux jointures, les données étaient manquantes (parce que le sous-requête peut renvoyer une valeur nulle qui omettrait toute la ligne).

Était-ce utile?

La solution

Je recommande d'obtenir les données dans une var table d'abord, peut-être 2 Table vars, 1 pour 12 et 1 pour 16 ProductID. A partir de ces tables vars, calculer au besoin les AVG en, puis revenir Tose du sp.

DECLARE @OrderDetails12 TABLE(
        DateFulfilled DATETIME,
        OrderTime FLOAT
)

INSERT INTO @OrderDetails12
SELECT  DateFulfilled,
        OrderTime
FROM    OrderDetails
WHERE   ProductID = 12
AND     DateDiff(day, DateFulfilled, GetDate()) <= 90
and CustomerNumber = @CustomerNumber

DECLARE @OrderDetails16 TABLE(
        DateFulfilled DATETIME,
        OrderTime FLOAT
)

INSERT INTO @OrderDetails16
SELECT  DateFulfilled,
        OrderTime
FROM    OrderDetails
WHERE   ProductID = 16
AND     DateDiff(day, DateFulfilled, GetDate()) <= 90
and CustomerNumber = @CustomerNumber

En outre, la création des bons index sur la table, aidera beaucoup.

Autres conseils

Quelle serait la quantité de données QUITTER être le serveur de base de données si elle était désagrégée, et combien de temps pour faire cette opération? La différence de la taille des données orientera si le temps de calcul sur le serveur est compensé par le temps de transfert et le calcul local.

De plus - regardez que l'utilisation de DATEDIFF et changer pour être plus facile de le faire optimisable (essayer DateFullfilled> = SomeCalculatedDate1 au lieu de DATEDIFF) - revoir votre plan d'exécution pour vous assurer qu'il est en mesure d'utiliser un index seek (meilleur) ou balayage d'index (bien) au lieu d'un table_scan.

En outre, assurez-vous il y a un index sur CustomerNumber, ProduceID, DateFulfilled.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top