При работе с информационными системами на платформе 1С:Предприятие 8.3, особенно с нетиповыми или отраслевыми конфигурациями, пользователи часто сталкиваются с проблемой низкой производительности при проведении или отмене проведения документов. Эта проблема может быть особенно острой, когда речь идет о документах с большим количеством строк, выполняющих движения по регистрам бухгалтерии. Рассмотрим, как провести диагностику и найти решение для таких случаев.
Представьте ситуацию: у вас есть документ с 5000 строк, который должен отражать зарплату в двух регистрах бухгалтерии. Проведение такого документа занимает до 15 минут, при этом отладчик показывает, что сама процедура ОбработкаПроведения занимает лишь треть этого времени. Оставшиеся минуты приложение "висит" без видимого выполнения кода. Еще более загадочной кажется отмена проведения, которая также длится несколько минут, но при этом отладчик вообще не фиксирует выполнение каких-либо строк кода.
Почему так происходит? Дело в том, что отладчик 1С фиксирует только выполнение кода, написанного на встроенном языке. Значительная часть времени может уходить на внутренние механизмы платформы и операции с базой данных, которые находятся "за кулисами" кода. Это могут быть клиент-серверные взаимодействия, передача данных, а также самые ресурсоемкие операции – запись и обновление данных в СУБД, в частности, работа с таблицами итогов регистров.
Чтобы понять, что именно происходит во время "подвисаний", нам потребуется заглянуть в работу базы данных. Для баз на MS SQL Server нашим главным помощником станет SQL Server Profiler.
Использование SQL Server Profiler
SQL Profiler позволяет отслеживать запросы, выполняемые к базе данных, и анализировать их производительность. Запустите Profiler, настройте захват событий (минимум: SQL:BatchCompleted, RPC:Completed, Duration, Reads, Writes) и начните трассировку перед выполнением операции проведения или отмены проведения документа.
Мы увидим, какие запросы выполняются, сколько времени они занимают (поле Duration), сколько данных читается и записывается (поля Reads и Writes). В нашем случае, при отмене проведения, Profiler показывает два одинаковых запроса типа UPDATE, каждый из которых выполняется 160-190 секунд:
exec sp_executesql N'UPDATE T2 SET _Fld34250 = T2._Fld34250 + T1._Fld34250, _TurnoverDt34267 = T2._TurnoverDt34267 + T1._TurnoverDt34267, _TurnoverCt34268 = T2._TurnoverCt34268 + T1._TurnoverCt34268, _Turnover34269 = T2._Turnover34269 + T1._Turnover34269, _Fld34251 = T2._Fld34251 + T1._Fld34251, _TurnoverDt34270 = T2._TurnoverDt34270 + T1._TurnoverDt34270, _TurnoverCt34271 = T2._TurnoverCt34271 + T1._TurnoverCt34271, _Turnover34272 = T2._Turnover34272 + T1._Turnover34272, _Fld34252 = T2._Fld34252 + T1._Fld34252, _TurnoverDt34273 = T2._TurnoverDt34273 + T1._TurnoverDt34273, _TurnoverCt34274 = T2._TurnoverCt34274 + T1._TurnoverCt34274, _Turnover34275 = T2._Turnover34275 + T1._Turnover34275, _Fld34253 = T2._Fld34253 + T1._Fld34253, _TurnoverDt34276 = T2._TurnoverDt34276 + T1._TurnoverDt34276, _TurnoverCt34277 = T2._TurnoverCt34277 + T1._TurnoverCt34277, _Turnover34278 = T2._Turnover34278 + T1._Turnover34278, _Fld34254 = T2._Fld34254 + T1._Fld34254, _TurnoverDt34279 = T2._TurnoverDt34279 + T1._TurnoverDt34279, _TurnoverCt34280 = T2._TurnoverCt34280 + T1._TurnoverCt34280, _Turnover34281 = T2._Turnover34281 + T1._Turnover34281, _Fld34255 = T2._Fld34255 + T1._Fld34255, _TurnoverDt34282 = T2._TurnoverDt34282 + T1._TurnoverDt34282, _TurnoverCt34283 = T2._TurnoverCt34283 + T1._TurnoverCt34283, _Turnover34284 = T2._Turnover34284 + T1._Turnover34284
FROM #tt23 T1 WITH(NOLOCK)
INNER JOIN dbo._AccRgAT234286 T2
ON T1._Period = T2._Period AND T1._AccountRRef = T2._AccountRRef AND T1._Fld34245RRef = T2._Fld34245RRef AND ((T1._Fld34246RRef = T2._Fld34246RRef OR T1._Fld34246RRef IS NULL AND T2._Fld34246RRef IS NULL)) AND ((T1._Fld34247RRef = T2._Fld34247RRef OR T1._Fld34247RRef IS NULL AND T2._Fld34247RRef IS NULL)) AND T1._Fld34248RRef = T2._Fld34248RRef AND T1._Fld34249 = T2._Fld34249 AND T1._Fld1104 = T2._Fld1104 AND (T1._Value1_TYPE = T2._Value1_TYPE AND T1._Value1_S = T2._Value1_S AND T1._Value1_RTRef = T2._Value1_RTRef AND T1._Value1_RRRef = T2._Value1_RRRef OR T1._Value1_TYPE IS NULL AND T1._Value1_S IS NULL AND T1._Value1_RTRef IS NULL AND T1._Value1_RRRef IS NULL AND T2._Value1_TYPE IS NULL AND T2._Value1_S IS NULL AND T2._Value1_RTRef IS NULL AND T2._Value1_RRRef IS NULL) AND (T1._Value2_TYPE = T2._Value2_TYPE AND T1._Value2_S = T2._Value2_S AND T1._Value2_RTRef = T2._Value2_RTRef AND T1._Value2_RRRef = T2._Value2_RRRef OR T1._Value2_TYPE IS NULL AND T1._Value2_S IS NULL AND T1._Value2_RTRef IS NULL AND T1._Value2_RRRef IS NULL AND T2._Value2_TYPE IS NULL AND T2._Value2_S IS NULL AND T2._Value2_RTRef IS NULL AND T2._Value2_RRRef IS NULL) AND T2._Splitter = P1 WHERE (T1._EDCount = @P2) AND (T2._Fld1104 = @P3)',N'P1 numeric(10),@P2 numeric(10),@P3 numeric(10)',0,2,0
Из этого запроса мы видим, что обновление происходит в таблице с именем dbo._AccRgAT234286. Это таблица итогов регистра бухгалтерии.
Анализ плана выполнения SQL-запроса
Чтобы понять, почему именно этот запрос так долго выполняется, нам необходимо проанализировать его план выполнения. Скопируйте текст запроса из Profiler'а в SQL Server Management Studio (SSMS).
После выполнения запроса в нижней части окна SSMS появится вкладка "Execution Plan". Мы увидим графическое представление того, как SQL Server собирается выполнить запрос: какие индексы используются, какие таблицы сканируются или ищутся, какие операции соединения (JOIN) выполняются и сколько ресурсов каждая операция потребляет. Частые проблемы, которые можно обнаружить: полное сканирование таблиц вместо использования индексов, неэффективные соединения, устаревшая статистика.
Медленное обновление таблиц итогов регистра бухгалтерии — это классическая проблема. Давайте разберем ее по шагам.
Особенности регистров бухгалтерии в 1С
Регистры бухгалтерии (РБ) — это мощный и гибкий механизм для учета, поддерживающий двойную запись, план счетов и до трех субконто для каждого счета. Однако за эту гибкость приходится платить производительностью. По сравнению с регистрами накопления (РН) и регистрами сведений (РС), РБ являются более ресурсоемкими, особенно при больших объемах движений. Использовать два РБ с 5000 строками в документе для зарплаты, как в нашем случае, может быть архитектурно неоптимальным решением, если нет строгих требований к ведению именно бухгалтерского учета по этим данным.
Роль таблиц итогов (_AccRgAT)
Таблицы с префиксом _AccRgAT (_AccRgAT234286 в нашем примере) — это таблицы итогов регистра бухгалтерии. Они хранят агрегированные данные (остатки и обороты) по счету, периоду и измерениям (субконто). Эти таблицы создаются платформой для ускорения формирования отчетов, которым нужны агрегированные данные. При каждом проведении или отмене проведения документа платформа автоматически обновляет соответствующие записи в этих таблицах. Если в регистре много измерений и ресурсов, а также активно ведутся записи, обновление этих таблиц может быть очень долгим.
Большое количество полей в UPDATE запросе
Проанализируем запрос из Profiler'а. Мы видим, что в запросе обновляется 18 полей в таблице T2 (которая является таблицей итогов). Каждое из этих полей, скорее всего, соответствует ресурсам и оборотам (_FldXXXXX, _TurnoverDtXXXXX, _TurnoverCtXXXXX, _TurnoverXXXXX) регистра бухгалтерии. Чем больше полей нужно обновить, тем больше работы для СУБД, особенно если эти поля имеют сложную структуру или требуют пересчета.
По информации из 1С:ИТС, механизм итогов для регистров бухгалтерии может создавать до четырех таблиц итогов для каждого счета в плане счетов: для остатков, оборотов, дебетовых оборотов и кредитовых оборотов. Количество этих таблиц зависит от настроек плана счетов и регистра. Обновление каждой из них при большом количестве движений и измерений становится узким местом.
Контекстные вызовы клиент-сервер
Вызов серверной процедуры или функции из клиентской части формы требует передачи всего контекста формы (ее реквизитов, элементов, параметров) на сервер и обратно. Этот процесс может быть достаточно затратным, особенно если форма содержит много данных или если клиент и сервер находятся на разных площадках с медленным каналом связи. Замеры производительности в отладчике не всегда учитывают время, затрачиваемое на передачу контекста и инициализацию серверной части, что может создавать ощущение "подвисания" без видимого выполнения кода.
Теперь, когда мы понимаем причины, перейдем к решениям.
Опыт автора темы показал, что отключение текущих итогов регистра значительно ускоряет операции. Время проведения уменьшилось на 15%, а время отмены проведения – в три раза.
Что такое "текущие итоги" и как их отключить?
Платформа 1С:Предприятие поддерживает два вида итогов: текущие (оперативные) и закрытые. Текущие итоги обновляются автоматически при каждом движении, обеспечивая актуальность данных. Однако их постоянное обновление может быть избыточным и ресурсоемким для определенных операций.
Для регистров бухгалтерии, которые используются в нетиповых механизмах, возможно программное управление режимом формирования итогов. Для временного отключения оперативного формирования итогов можно использовать методы объекта НаборЗаписейРегистраБухгалтерии.
// В начале процедуры проведения/отмены проведения документа
Движения.РегистрБухгалтерии1.Записывать = Истина;
Движения.РегистрБухгалтерии1.РежимЗаписи = РежимЗаписиДвижений.Замещать;
Движения.РегистрБухгалтерии1.ИспользоватьТекущиеИтоги = Ложь; // Отключаем текущие итоги
Движения.РегистрБухгалтерии2.Записывать = Истина;
Движения.РегистрБухгалтерии2.РежимЗаписи = РежимЗаписиДвижений.Замещать;
Движения.РегистрБухгалтерии2.ИспользоватьТекущиеИтоги = Ложь; // Отключаем текущие итоги
// ... ваш код формирования движений ...
// В конце процедуры проведения/отмены проведения документа
Движения.РегистрБухгалтерии1.Записать();
Движения.РегистрБухгалтерии2.Записать();
// Возможно, после операции нужно будет вручную пересчитать итоги, если они нужны для других отчетов
Важно: Отключение текущих итогов означает, что данные в таблицах итогов не будут обновляться автоматически. Это может привести к неактуальным данным в отчетах, которые используют итоги. Поэтому такое отключение следует применять осторожно, возможно, с последующим регламентным пересчетом итогов или включением их обратно после выполнения массовой операции.
Если речь идет о массовых операциях (например, загрузка или перепроведение большого количества документов), мы можем полностью отключить использование итогов для регистра на время выполнения этих операций, а затем включить их обратно и пересчитать.
Разделение итогов
Для регистров бухгалтерии существует специальный режим разделения итогов. Он позволяет нескольким пользователям одновременно обновлять записи в таблице остатков, даже если совпадают период, счет и значения измерений. Включение этого режима может значительно повысить параллельность работы и общую производительность системы в многопользовательской среде, если нет строгого контроля остатков. В режиме разделения итогов в таблицу итогов добавляется дополнительное техническое поле-разделитель (_Splitter), что позволяет создавать несколько записей итогов с разными значениями разделителя для одних и тех же ключей, снимая ограничение на ожидание.
Этот режим настраивается в конфигураторе для каждого регистра отдельно и требует понимания его влияния на логику работы с данными.
Медленные SQL-запросы почти всегда указывают на проблемы с настройкой базы данных.
Анализ плана выполнения запроса и индексы
Внимательно изучите план выполнения запроса, который был получен в SSMS. Мы увидим, какие операции являются самыми "дорогими" (помечены красным или имеют большой процент стоимости). Чаще всего это операции Table Scan (полное сканирование таблицы) или Index Scan (полное сканирование индекса) вместо Index Seek (точечный поиск по индексу).
Проверьте наличие и состав индексов для таблицы dbo._AccRgAT234286. Индексы должны включать поля, по которым происходит соединение (T1._Period = T2._Period AND T1._AccountRRef = T2._AccountRRef AND ...) и фильтрация (WHERE (T1._EDCount = @P2) AND (T2._Fld1104 = @P3)). Создание или изменение индексов может значительно ускорить запрос. Однако слишком много индексов, или индексы с большим количеством полей, могут замедлять операции записи, так как при каждом изменении данных индексы также должны обновляться.
MS SQL Server имеет ограничение на количество столбцов в индексе (не более 16), что следует учитывать при формировании индексов для регистров с большим количеством измерений.
Общие настройки SQL Server
Для оптимальной работы 1С с MS SQL Server рекомендуется:
Max degree of parallelism = 1, чтобы SQL Server не пытался распараллеливать выполнение одного запроса, что часто приводит к накладным расходам.Иногда проблема производительности кроется в самом подходе к хранению данных.
Когда стоит избегать регистров бухгалтерии для больших объемов данных?
Для таких задач, как детальный учет зарплаты с 5000 строками в документе, где требуется хранение оборотов или остатков по множеству аналитик, регистры бухгалтерии могут быть не самым производительным выбором. Если нам не нужна именно полноценная двойная запись по плану счетов, а требуется лишь накопление данных с определенными измерениями, то лучше использовать другие типы регистров.
Альтернативы: Регистры накопления и Регистры сведений
Радикальное изменение архитектуры с РБ на РН/РС в уже работающей отраслевой конфигурации может быть сложным, но это важный аспект для рассмотрения при проектировании новых подсистем или при значительных переработках.
Тестирование и исправление базы данных
Регулярно выполняйте процедуру "Тестирование и исправление" информационной базы с опцией "Пересчет итогов". Это помогает устранять логические ошибки в базе данных, пересчитывать и восстанавливать целостность итогов, что может решить проблемы, связанные с "фантомными" записями или некорректными итогами.
Свертка информационной базы
Если база данных содержит данные за очень долгие периоды, мы можем рассмотреть возможность свертки информационной базы. Эта операция архивирует старые, закрытые периоды и удаляет их из оперативной базы, значительно уменьшая ее размер и, соответственно, время работы с итогами и запросами.
Проверка прав доступа
Иногда проблемы с производительностью могут быть связаны с некорректно настроенными правами доступа. Если пользователь выполняет операции под ограниченными правами, платформа может тратить дополнительное время на проверку доступности данных и объектов. Проведите тестирование операции под полными правами, чтобы исключить или подтвердить влияние прав доступа на скорость.
Технологический журнал 1С
Для более глубокого анализа производительности можно настроить технологический журнал 1С. Он собирает подробную информацию о внутренних событиях платформы, включая время выполнения различных операций, блокировки, запросы к СУБД и клиент-серверные взаимодействия. Анализ данных технологического журнала может дать полную картину происходящего.
Проблемы с производительностью в 1С — это комплексные задачи, требующие системного подхода. Мы рассмотрели методы диагностики с помощью SQL Profiler, проанализировали специфику работы регистров бухгалтерии и предложили практические решения, такие как управление текущими итогами, оптимизация SQL Server и, при необходимости, пересмотр архитектуры хранения данных. Применяя эти подходы, мы сможем эффективно выявлять и устранять "тормоза" в работе нашей системы.