Usando T-SQL AVG ou tomando a média após os resultados retornados usando o LINQ
-
20-09-2019 - |
Pergunta
Eu tenho um procedimento armazenado que usa uma visão para extrair 6 médias. O banco de dados SQL é o SQL Server 2000. Quando o executo no analisador de consultas, leva cerca de 9 segundos. O que posso fazer para obter melhor desempenho? Devo devolver as linhas usando o LINQ e determinar uma média dessa maneira? Será mais rápido?
Aqui está um exemplo do meu sproc atual:
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
Além disso, deixe -me esclarecer a visão mencionada acima. Como este é o SQL Server 2000, não posso usar uma visualização indexada porque ele usa uma subconsulta. Suponho que isso possa ser reescrito para usar junções. No entanto, a última vez que pegamos uma consulta e a reescrevemos para usar junções, os dados estavam faltando (porque a subconsulta pode retornar um valor nulo que omitiria a linha inteira).
Solução
Eu recomendaria colocar os dados em uma tabela VAR primeiro, talvez 2 vars de tabela, 1 para 12 e 1 para 16 ProductId. A partir dessas vars de tabela, calcule os AVGs conforme necessário e retorne a Tose do 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
Além disso, criar os índices corretos na tabela ajudará muito.
Outras dicas
Qual seria a quantidade de dados que deixariam o servidor de banco de dados se não for agregado e por quanto tempo fazer essa operação? A diferença no tamanho dos dados orientará se o tempo de cálculo no servidor é superado pelo tempo de transferência e pelo cálculo local.
Além disso - olhe para isso DATEDIFF
Uso e altere -o para ser mais fácil torná -lo otimizável (tente datefullFilled> = SomecalCulatedDate1 em vez de DATEDIFF
) - Revise seu plano de execução para garantir que ele seja capaz de usar um índice procurar (melhor) ou digitalização de índice (boa) em vez de um tabela_scan.
Além disso, verifique se há um índice no CustomerNumber, ProductId, Datefilless.