В процессе разработки и сопровождения систем на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с проблемой существенного замедления работы отчетов и алгоритмов при увеличении объема данных в регистрах накопления. Особенно остро эта проблема проявляется при обращении к виртуальным таблицам Остатки, Обороты или ОстаткиИОбороты. Давайте разберем причины возникновения этой проблемы и рассмотрим пошаговые методы ее решения, основываясь на практическом опыте специалистов и рекомендациях вендора.
Для начала проанализируем ситуацию. Виртуальные таблицы 1С не существуют в физической структуре базы данных SQL. Они формируются платформой динамически в момент выполнения запроса на основе физических таблиц итогов. Если запрос к виртуальной таблице написан некорректно, система вынуждена сканировать огромные объемы данных, что приводит к блокировкам и длительному ожиданию ответа.
Основными причинами низкой производительности являются:
ГДЕ вместо параметров виртуальной таблицы.ОстаткиИОбороты там, где достаточно одной из простых таблиц.Рассмотрим подробнее важнейшее правило: отборы должны передаваться только через параметры виртуальной таблицы. Если мы накладываем условие после обращения к таблице (в секции ГДЕ), платформа сначала выберет все итоги из базы, а уже потом отфильтрует их. Это критическая ошибка.
Посмотрим на пример неправильного кода:
ВЫБРАТЬ
ПродажиОбороты.Номенклатура,
ПродажиОбороты.КоличествоОборот
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода) КАК ПродажиОбороты
ГДЕ
ПродажиОбороты.Склад = &Склад
Проанализируем этот запрос. Здесь система сначала рассчитает обороты по всей номенклатуре и всем складам, и только потом отсечет лишнее. Чтобы исправить это, перенесем отбор в параметры:
ВЫБРАТЬ
ПродажиОбороты.Номенклатура,
ПродажиОбороты.КоличествоОборот
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , Склад = &Склад) КАК ПродажиОбороты
В данном случае условие Склад = &Склад попадет в SQL-запрос в секцию WHERE при обращении к физической таблице итогов, что значительно ускорит получение результата.
Разберем ситуацию, когда даже при правильных параметрах запрос работает медленно. Проблема может заключаться в индексах. В 1С измерения регистров индексируются автоматически, но порядок измерений в конфигураторе имеет решающее значение. Индекс работает наиболее эффективно, если отбор в запросе соответствует порядку полей в индексе.
Практический совет: если вы часто делаете отбор по конкретному измерению (например, Проект), которое находится в списке измерений низко, попробуйте поднять его выше или установите свойство Индексировать в значение Индексировать или Индексировать с доп. упорядочиванием.
Посмотрим, как проверить актуальность индексов:
УстановитьИспользованиеИтогов(Истина)).Многие разработчики используют таблицу ОстаткиИОбороты для получения всех данных сразу. Однако эта таблица является самой "тяжелой", так как она соединяет данные из нескольких таблиц итогов. Разберем по шагам, как оптимизировать такие запросы.
Если вам нужны только остатки на начало и конец периода, а также обороты, рассмотрите возможность использования двух отдельных таблиц — Остатки и Обороты — и их последующего соединения в запросе. Это зачастую работает быстрее, так как Остатки берутся из одной таблицы итогов, а Обороты — из другой.
Пример оптимизированного подхода с использованием временных таблиц:
// Сначала получаем остатки в отдельную временную таблицу
ВЫБРАТЬ
Остатки.Номенклатура,
Остатки.КоличествоОстаток КАК НачОстаток
ПОМЕСТИТЬ ВТ_Начало
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&НачалоПериода, Склад = &Склад) КАК Остатки;
// Затем получаем обороты за период
ВЫБРАТЬ
Обороты.Номенклатура,
Обороты.КоличествоПриход,
Обороты.КоличествоРасход
ПОМЕСТИТЬ ВТ_Обороты
ИЗ
РегистрНакопления.ТоварыНаСкладах.Обороты(&НачалоПериода, &КонецПериода, , Склад = &Склад) КАК Обороты;
После этого мы просто соединяем эти таблицы по полю Номенклатура. Такой метод позволяет СУБД строить более оптимальные планы выполнения запросов.
Рассмотрим ситуацию, когда отбор в виртуальной таблице должен производиться по сложному списку (например, по номенклатуре из определенного сегмента). Использование оператора В ИЕРАРХИИ или просто В (&Список) с очень большим списком может замедлить запрос.
Эффективным решением будет предварительная выгрузка списка объектов во временную таблицу и последующее использование этой таблицы в параметрах виртуальной таблицы. В 1С 8.3 для этого используется конструкция В (ВЫБРАТЬ ... ИЗ ВТ_Список).
ВЫБРАТЬ
Обороты.Номенклатура,
Обороты.СуммаВыручкиОборот
ИЗ
РегистрНакопления.Продажи.Обороты(,, , Номенклатура В (ВЫБРАТЬ Т.Номенклатура ИЗ ВТ_НужныеТовары КАК Т)) КАК Обороты
Если система тормозит при записи в регистр (проведении документов), проблема может быть в блокировках таблиц итогов. Для борьбы с этим в 1С предусмотрен режим Разделение итогов. Проанализируем, как это работает: платформа создает несколько записей в таблице итогов для одного и того же набора измерений, что позволяет разным сеансам записывать данные одновременно без ожидания блокировки.
Важно: убедитесь, что в свойствах регистра накопления стоит галочка Разрешить разделение итогов. Это критично для высоконагруженных систем, где много пользователей одновременно проводят документы по одним и тем же складам или товарам.
Мы проанализировали основные методы оптимизации работы с регистрами накопления. Для достижения максимальной скорости работы ваших отчетов и алгоритмов всегда соблюдайте три главных правила:
ГДЕ.Используя эти техники, вы сможете значительно повысить отзывчивость системы и стабильность работы пользователей даже на очень больших базах данных.