Использование T-SQL AVG или получение среднего значения после результатов, возвращенных с помощью LINQ

StackOverflow https://stackoverflow.com/questions/1757446

Вопрос

У меня есть хранимая процедура, которая использует представление для извлечения 6 средних значений.Базой данных SQL является SQL Server 2000.Когда я запускаю его в анализаторе запросов, это занимает примерно 9 секунд.Что я могу сделать, чтобы повысить производительность?Должен ли я возвращать строки с помощью LINQ и определять среднее значение таким образом?Будет ли это быстрее?

Вот пример моего текущего sproc:

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

Кроме того, позвольте мне прояснить точку зрения, упомянутую выше.Поскольку это SQL Server 2000, я не могу использовать индексированное представление, потому что оно использует подзапрос.Я полагаю, это можно переписать, чтобы использовать соединения.Однако в последний раз, когда мы взяли запрос и переписали его для использования объединений, данные отсутствовали (поскольку подзапрос может возвращать нулевое значение, в котором будет опущена вся строка).

Это было полезно?

Решение

Я бы рекомендовал сначала занести данные в табличный var, возможно, в 2 табличных vars, 1 для 12 и 1 для 16 ProductID.Исходя из этих табличных переменных, вычислите средние значения по мере необходимости, а затем верните их из 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

Кроме того, создание правильных индексов в таблице очень поможет.

Другие советы

Каков был бы объем данных, покидающих сервер базы данных, если бы они были неагрегированы, и как долго требовалось для выполнения этой операции?Разница в размере данных будет определять, перевешивается ли время вычисления на сервере временем передачи и локальным вычислением.

Кроме того - посмотрите на это DATEDIFF использование и измените его, чтобы упростить его оптимизацию (попробуйте DateFullfilled >= SomeCalculatedDate1 вместо DATEDIFF) - просмотрите свой план выполнения, чтобы убедиться, что он может использовать поиск по индексу (best) или сканирование индекса (good) вместо table_scan.

Кроме того, убедитесь, что есть индекс для CustomerNumber, ProduceID, DateFulfilled.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top