Тормозит запрос к регистру бухгалтерии 1С: пять мест, где теряется время, и как их починить
Почему регистр бухгалтерии — особый случай
Регистр бухгалтерии хранит проводки с корреспонденцией счетов. Каждое движение — это сразу пара «дебет-кредит» плюс набор субконто по обеим сторонам. Виртуальные таблицы платформы (Обороты, Остатки, ОстаткиИОбороты, ДвиженияССубконто) собирают результат из реальных таблиц БД, разворачивая корреспонденцию. Чем больше счетов и субконто вы тащите за раз — тем шире промежуточный набор, и тем дольше всё это считается.
Пять точек, где обычно теряется время
1. Фильтр счёта в условии ГДЕ, а не в параметре виртуальной таблицы
Самая частая ошибка: виртуальная таблица собирает обороты по всем счетам, и только потом результат отфильтровывается в условии ГДЕ. Платформа уже потратила время на счета, которые вам не нужны. Правильно — передать фильтр в параметры самой виртуальной таблицы: у Оборотов / Остатков / ОстаткиИОбороты есть отдельные параметры для счёта и для произвольного условия (последний по позиции). Точную сигнатуру и порядок аргументов смотрите в конструкторе запроса в Конфигураторе — он подставляет именованные параметры сам, и риск перепутать позицию исчезает.
2. Чтение лишних видов субконто
Если регистр бухгалтерии хранит данные с тремя видами субконто, а вам в отчёте нужны только два, и при этом вы не указали конкретные виды субконто в параметрах виртуальной таблицы — платформа развернёт все три. Особенно дорого это на счетах с тяжёлыми субконто типа «Документ расчётов с контрагентом» (там миллионы значений). Передавайте только нужные виды субконто — это часто даёт лучший выигрыш по времени.
3. Соединение временной таблицы без индекса
Поместили промежуточный результат в ВТ, потом соединяете с другой таблицей по контрагенту, и удивляетесь, почему запрос стал медленнее. Платформа делает полный перебор по ВТ, потому что у неё нет индекса. Добавьте ИНДЕКСИРОВАТЬ ПО к ВТ — на ВТ от сотен тысяч строк выигрыш заметный. На маленьких ВТ (несколько тысяч строк) разница может оказаться нулевой или даже отрицательной — индекс строится дольше, чем экономит.
// ВТ с явным индексом по полю соединения
ВЫБРАТЬ
Реализация.Контрагент КАК Контрагент,
Реализация.СуммаДокумента КАК СуммаДок
ПОМЕСТИТЬ ВТ_Реализации
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
И Реализация.Проведен = ИСТИНА
ИНДЕКСИРОВАТЬ ПО
Контрагент
;
// Теперь соединение по Контрагенту работает быстро
ВЫБРАТЬ
ВТ_Реализации.Контрагент,
ВТ_Реализации.СуммаДок,
Контрагенты.Наименование
ИЗ
ВТ_Реализации КАК ВТ_Реализации
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты
ПО ВТ_Реализации.Контрагент = Контрагенты.Ссылка
4. Запрос в цикле
Классика: цикл по списку контрагентов, внутри — запрос «дай мне остаток на счёте 62 на дату». Тысяча контрагентов — тысяча запросов. Это убивает производительность любой базы, не только 1С. Перепишите как один запрос со списком контрагентов в параметре виртуальной таблицы — и тысяча обращений к серверу превратятся в одно.
5. Чтение по движениям вместо итогов
Платформа поддерживает итоги регистра бухгалтерии — это таблицы с предрассчитанными остатками на конец каждого периода. Если ваш отчёт показывает остаток на 1-е число месяца — он должен читать итог, а не пересчитывать сумму движений с начала эксплуатации. Виртуальные таблицы Остатки / ОстаткиИОбороты используют итоги, если они актуальны. Если регламентное задание «Пересчёт итогов» не успевает или вообще не настроено — итоги не актуальны, и платформа честно перебирает движения. На крупной базе с многолетней историей разница между чтением по актуальным итогам и пересчётом движений может достигать одного-двух порядков; точная величина зависит от глубины истории и СУБД.
Сравнение подходов на одну и ту же задачу
| Задача | Что обычно делают | Что лучше работает |
|---|---|---|
| Обороты по группе счетов за период | Обороты(...) с пустыми параметрами + ГДЕ Счёт В (...) после |
Передать фильтр счёта прямо в параметры виртуальной таблицы (точную позицию подставит конструктор запроса) |
| Остаток на дату по контрагенту | Запрос в цикле по контрагентам | Один запрос с массивом контрагентов в параметре Условие |
| Соединение оборотов с реквизитами контрагента | Прямое соединение виртуальной таблицы со справочником | Виртуальную таблицу — в ВТ с индексом, потом соединение |
| Остаток на 1-е число месяца | Сумма движений с начала эксплуатации | Виртуальная таблица Остатки + актуальные итоги |
Прежде чем оптимизировать — измерьте. На клиент-серверной базе включите технологический журнал на событиеDBMSSQL(илиDBPOSTGRS, в зависимости от СУБД) с фильтром по своему сеансу, выполните отчёт один раз и посмотрите, какой именно SQL-запрос платформа отправила в базу и сколько он шёл. На файловой базе используйте замер производительности в Конфигураторе. В обоих случаях это сразу покажет, где время теряется — и часто вы поймёте, что оптимизировали не ту часть.
Чек-лист диагностики тяжёлого запроса
- Найдите сам запрос: для отчётов — кнопка «Структура запроса» в конструкторе СКД; для произвольных модулей — текст запроса в коде.
- Проверьте, что все известные ограничения (период, счёт, организация, контрагент) переданы в параметры виртуальной таблицы, а не в
ГДЕ. - Если есть ВТ — убедитесь, что у неё
ИНДЕКСИРОВАТЬ ПОпо полям, по которым она потом соединяется. - Удалите из выборки все колонки и измерения, которые вам не нужны для конечного результата.
- Убедитесь, что виды субконто перечислены явно — иначе платформа разворачивает все.
- Проверьте актуальность итогов регистра: если запрос идёт по остаткам и итоги не актуальны — сначала разберитесь с регламентным заданием их пересчёта.
- Если запрос работает с большим количеством сущностей — нет ли его внутри цикла? Перепишите цикл в массив-параметр.
- Повторите замер. Если время почти не изменилось — скорее всего, вы оптимизировали не то место: вернитесь к технологическому журналу и найдите реальное узкое место.
Типичные ошибки
- «Оптимизация запроса под глазом». Сначала замер технологическим журналом, потом правка. Без замеров вы можете два часа улучшать запрос, который вообще не был узким местом.
- Тащить весь регистр в ВТ, потом фильтровать. Виртуальные таблицы — это и есть фильтр. Если вы кладёте «все обороты за квартал» в ВТ, чтобы потом отбросить 95% — вы делаете лишнюю работу за платформу.
- Соединение без индексов. Любая ВТ, к которой будет
ЛЕВОЕ СОЕДИНЕНИЕилиВНУТРЕННЕЕ СОЕДИНЕНИЕ, должна быть проиндексирована по соединительному полю. - Игнорирование закрытия периода. Если у вас закрытый период и регулярно прогоняемые тяжёлые отчёты — рассмотрите кэширование результатов в отдельный регистр сведений. Запрос к нему займёт миллисекунды вместо секунд.
- «Запрос медленный — значит, нужен индекс СУБД». В 1С платформа сама управляет индексами реальных таблиц на основе ваших измерений регистров. Если измерение редко используется — не используйте его в фильтре. Лезть в индексы СУБД через её менеджмент-консоль обычно не нужно и опасно: при обновлении конфигурации платформа их пересоздаёт по-своему.
- Считаете «всё за всё время». Если отчёту достаточно последних трёх месяцев — не запрашивайте пять лет «на всякий случай». Каждый лишний период умножает время выполнения.
Перейти в каталог решений →