1. Исходная ситуация и "диагностика"
Шаг 1: Воспроизведение проблемы. Запускаем отчет. Убеждаемся, что он действительно работает неприемлемо долго.Шаг 2: Снятие "слепка" производительности. Используем
v8perf.epf (монитор производительности). Видим, что основное время съедает один тяжелый запрос.Шаг 3: Анализ плана запроса. Копируем текст запроса в Консоль запросов и смотрим план.
2. Исходный "проблемный" запрос
bslВЫБРАТЬ
Менеджеры.Ссылка КАК Менеджер,
ВЫБОР
КОГДА Реализация.Проведен ТОГДА "Проведен"
ИНАЧЕ "Не проведен"
КОНЕЦ КАК Статус,
СУММА(Реализация.Сумма) КАК СуммаПродаж
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Менеджеры КАК Менеджеры
ПО Реализация.Менеджер = Менеджеры.Ссылка
ГДЕ
Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
СГРУППИРОВАТЬ ПО
Менеджеры.Ссылка,
Статус // Группировка по вычисляемому полю!
Что не так?
-
Группировка по вычисляемому полю: Это заставляет СУБД сначала выполнить вычисление
Статусдля КАЖДОЙ строки, а потом группировать. -
Отсутствие индексов: Поля
ДатаиМенеджерв документе "Реализация" могут быть не проиндексированы. -
В плане запроса виден
Table Scanпо таблице документа иSortперед группировкой.
3. Процесс оптимизации
Шаг 1: Убираем группировку по вычисляемому полю.
-
Выносим условие в
GROUP BYявно.
СГРУППИРОВАТЬ ПО
Менеджеры.Ссылка,
Реализация.Проведен // Группируем по булеву полю
-
А статус выводим так:
ВЫБРАТЬ
...
ВЫБОР
КОГДА Реализация.Проведен ТОГДА "Проведен"
ИНАЧЕ "Не проведен"
КОНЕЦ КАК Статус, // Теперь это вычисление делается ПОСЛЕ группировки
Шаг 2: Убеждаемся, что есть индексы.
-
Запрашиваем у админа БД создание индекса по полям
ДатаиМенеджердля таблицы документа "Реализация".
Шаг 3 (опционально): Используем временную таблицу.
-
Если запрос все еще сложный, разбиваем его. Сначала помещаем отобранные по индексированным полям данные во ВТ, а потом уже агрегируем.
4. Окончательный, оптимизированный запрос
bsl// 1. Помещаем отобранные документы во ВТ
ВЫБРАТЬ
Реализация.Ссылка,
Реализация.Менеджер,
Реализация.Сумма,
Реализация.Проведен
ПОМЕСТИТЬ ВТ_Реализация
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода; // Индекс по дате работает здесь!
// 2. Делаем итоговый запрос с соединением и группировкой
ВЫБРАТЬ
Менеджеры.Ссылка КАК Менеджер,
ВЫБОР
КОГДА ВТ_Реализация.Проведен ТОГДА "Проведен"
ИНАЧЕ "Не проведен"
КОНЕЦ КАК Статус,
СУММА(ВТ_Реализация.Сумма) КАК СуммаПродаж
ИЗ
ВТ_Реализация КАК ВТ_Реализация
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Менеджеры КАК Менеджеры
ПО ВТ_Реализация.Менеджер = Менеджеры.Ссылка
СГРУППИРОВАТЬ ПО
Менеджеры.Ссылка,
ВТ_Реализация.Проведен5. Итоговый результат
-
Было: > 3 минут.
-
Стало: ~ 2-3 секунды.
-
Что дало наибольший эффект:
-
Создание индекса по полю
Дата. -
Изменение логики группировки.
-
Разбивка запроса на два простых шага через ВТ.
-
Заключение:
-
Оптимизация — это последовательный процесс: диагностика -> анализ -> точечные изменения -> проверка результата.
-
Часто для успеха не нужна сложная магия, а нужно исправить 1-2 ключевые ошибки, мешающие СУБД работать эффективно.

