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