Оптимизация формирования отчётов

Добрый день, нам ежемесячно надо формировать и отправлять месячные отчёты для сдачи объектов. Мы столкнулись с тем что система не может обработать такое количество данных и выкидывает Учётные записи клиентов и перестает работать служба Сервер ЛЭРС. Для оптимизации запросов мы предлагаем Вам решение данной проблемы:
Запрос

SELECT [t0].[Id], [t0].[EndDate], [t0].[CommLinkType], [t0].[EquipmentId], [t0].[PollErrorCount], [t0].[PollResult], [t0].[PollType]
FROM [Equipment] AS [e]
INNER JOIN (
    SELECT [t].[Id], [t].[CommLinkType], [t].[EndDate], [t].[EquipmentId], [t].[PollErrorCount], [t].[PollResult], [t].[PollType]
    FROM (
        SELECT [e0].[Id], [e0].[CommLinkType], [e0].[EndDate], [e0].[EquipmentId], [e0].[PollErrorCount], [e0].[PollResult], [e0].[PollType], ROW_NUMBER() OVER(PARTITION BY [e0].[EquipmentId] ORDER BY [e0].[EndDate] DESC) AS [row]
        FROM [EquipmentPollStatistics] AS [e0]
    ) AS [t]
    WHERE [t].[row] <= 1
) AS [t0] ON [e].[Id] = [t0].[EquipmentId]

берет все записи [EquipmentPollStatistics], нумерует и сортирует по [EquipmentId],[EndDate] чтобы получить последние даты статистики по [Equipment].
Этот запрос выполняется от 1 до 3 секунд и вызывается почти 9500 раз за сбор отчетности. И всего обрабатывает ~1,500,000 строк

Можно использовать

;with eps as (select EquipmentId,max(EndDate) EndDate FROM EquipmentPollStatistics AS eps group by eps.EquipmentId)
SELECT [t].[Id], [t].[CommLinkType], [t].[EndDate], [t].[EquipmentId], [t].[PollErrorCount], [t].[PollResult], [t].[PollType]
FROM eps
JOIN[EquipmentPollStatistics] AS [t] on [t].[EquipmentId]=eps.EquipmentId and [t].[EndDate]=eps.EndDate
JOIN [Equipment] AS [e] ON [e].[Id] = [t].[EquipmentId]

, который меньше секунды. А еще добавить Дату и индекс для даты в [EquipmentPollStatistics]

declare @dt date=dateadd(month,-6,getdate())
;with eps as (select EquipmentId,max(EndDate) EndDate FROM EquipmentPollStatistics AS eps where @dt<=EndDate group by eps.EquipmentId)
SELECT [t].[Id], [t].[CommLinkType], [t].[EndDate], [t].[EquipmentId], [t].[PollErrorCount], [t].[PollResult], [t].[PollType]
FROM eps
join [EquipmentPollStatistics] AS [t] on [t].[EquipmentId]=eps.EquipmentId and [t].[EndDate]=eps.EndDate
JOIN [Equipment] AS [e] ON [e].[Id] = [t].[EquipmentId]

Данное решение Нам предоставил наш Программист который непосредственно занимается разработками на Базе SQL.

1 лайк

Поддерживаю. Столкнулись с такой же проблемой.

Уточните, пожалуйста, тип отчёта и сущность (точка/объект). Плюс, скажите как вы формируете отчёты? Заданием, или вы вручную выбираете все объекты и формируете отчёты для них.

Мы не можем использовать прямые SQL-запросы, так как строим их с использованием Entity Framework. Нужно будет искать способы оптимизации в нём.

В частности, 3 секунды это совсем не много, однако, непонятно зачем они выполняются 95 тыс раз. Возможно, достаточно будет кэшировать результаты выборки минут на 10, и всё будет работать очень быстро.

Добрый день.
Уточните, пожалуйста, тип отчёта и сущность (точка/объект)?
Отчёт “Ведомость параметров” в точках учета.
Плюс, скажите как вы формируете отчёты?
Вручную, предварительно выделив нужные точки учета.

В частности, 3 секунды это совсем не много
Не соглашусь так как эти 3 секунду только на обработку команды а если учитывать и формирование отчета то уходит в среднем сек 5-8. Мы предлагаем проверенный запрос который обрабатывает данный менее 1 сек.

Да, но это в любом случае запрос аггрегированных сущностей, план исполнения которого гораздо сложнее, чем простой поиск по ключу. И мы повторяем для каждого отчёта один и тот же запрос из раза в раз. Даже если сократить его до 1 секунды, всё равно останется 9500 “лишних” секунд, а это практически два часа, которые можно разом удалить, сохранив результат выборки между запросами. Если это сделать, запрос выполнится только пару раз в процессе формирования отчётов, и там уже не будет играть роли сколько он занимает.

Однако, мы продумаем комплексное решение, оптимизировав выборку, и дополнительно проработав варианты с кэшированием.

Кстати, задания на автоматическое формирование отчётов работают немного по-другому, и в них запрос будет выполнен только один раз. Можете попробовать создать и запустить принудительно такое задание, экспортировав отчёты в папку. Результат должен появится намного быстрее и с меньшей нагрузкой на сервер.

Мы оптимизируем выборку статистики опроса в 3.52. Запрос переписали на более эффективный, но основная оптимизация - 10-минутный кэш статистики, который полностью уберёт эти запросы, которые могут выполняться довольно долго.

@lersbot update 3.52.0

Спасибо, надеемся ваша оптимизация будет эффективной. Всё таки на нашей большой базе запрос обрабатывался за 0, секунд это даже не 1 секунда. Так же наш программист сказал что можно ещё ограничить диапазон проверки из строк на пример в пол года, хотя время в 0 секунд меньше не стало. Надеемся на результат от вас. Ну очень ждём.