Современные учетные задачи производственных предприятий остаются достаточно сложными для любых систем, особенно работающих под высокой нагрузкой — большой документооборот или количество пользователей. И одними из самых сложных задач остаются задачи расчета себестоимости выпуска продукции.
Типовые конфигурации 1С, например, «1С:Управление производственным предприятием» (УПП) давно предлагают множество механизмов для упрощения данных расчетов, например, инструментарий механизма РАУЗ (расширенной аналитики учета затрат). Данный механизм действительно позволяет в некоторых случаях существенно упростить технически, а значит — ускорить функции расчета себестоимости. Проблема только в том, что использовать данный подход можно не всегда, и предприятиям приходится использовать старый добрый партионный учет, а вместе с ним — использовать процедуру восстановления партинного учета.
В большинстве случаев при существенном документообороте именно задача «восстановления партий» является самой трудоемкой и длительной в процессе закрытия месяца и расчета себестоимости. Давайте рассмотрим ее подробнее со всех сторон и разберем, какие здесь имеются пути для оптимизации и сокращения времени.
Первое, с чем приходится сталкиваться при выполнении проектов по оптимизации производительности процедуры восстановления партий — это устаревшие методы выполнения этой процедуры, а именно — полное перепроведение документов. Иногда это только определенные виды документов, участвующие в «партиях», иногда вообще все без разбора. Нам кажется, что данный подход идет с тех времен, когда действительно других альтернатив и не было, либо с тех конфигураций, в которых это единственный способ. Однако, сейчас для рассматриваемой нами конфигурации УПП это не так. В УПП есть более аккуратные и производительные механизмы для выполнения этих задач, а именно:
- Процедура восстановления последовательности партионного учета (отдельно УУ, БУ, организациям).
- Процедура восстановления взаиморасчетов (определения авансов).
Каждый из этих пунктов реализован отдельными обработками, которые вместо полного перепроведения документов выполняют только корректировку движений очень ограниченного числа регистров, за счет чего процесс выполняется несравнимо быстрее. Примерно так же поступает вторая обработка для восстановления взаиморасчетов. Кроме этого, если сравнивать работу этих механизмов с обычным перепроведением документов можно столкнуться со следующей проблемой, искажающей учетные данные: сортировка по дате документов, необходимая для расположения документов «в хронологическом порядке» работает с точностью до секунд, а в рамках одной секунды в системе могут присутствовать несколько разных документов (например, поступление и списание), от последовательности обработки которых будет зависеть сформированная стоимость. При обычном проведении нет никакой возможности обеспечить такой порядок и подобный расчет от раза к разу может давать разные результаты. Для решения этой проблемы в платформе предусмотрен специальный объект, «последовательность», который решает эту задачу и всегда гарантированно одинаково располагает документы по хронологии, и обработки восстановления последовательности всегда опираются именно на этот порядок.
Хорошо, но что если мы используем именно эти обработки и все равно процесс восстановления партий занимает длительное время, например, не успевает выполниться за ночь? При этом серверные мощности, чаще всего, простаивают (не имеют даже 30 % загрузки).
По нашему опыту, время обработки одного документа не превышает 0,2 — 0,8 секунд и сам код по корректировке движений написан достаточно хорошо. Чтобы получить существенный прирост, нужно сократить это время, например, с 0,2 сек до 0,05, что кажется практически невыполнимой задачей, даже если рассматривать возможность изменения не только кода конфигурации, но и тотальной замены оборудования на последние поколения процессоров и систем хранения данных на Flash/SSD. Неужели нет выхода?
Оказывается, он есть! Тут нам на помощь приходит наш опыт олимпиадного программирования и пытливый ум, который шепчет, казалось бы, абсурдную фразу — давайте сделаем процесс восстановления «последовательности» — «параллельным»! Казалось бы, это невозможно, ведь мы намеренно «расставляем» документы строго друг за другом и именно так их и обрабатываем. Это и объясняет медлительность процесса — он идет в один поток, ограничен производительностью одного ядра процессора серверов, которые, как правило, имеют достаточно много простаивающих в это время других ядер.
На самом деле, расположение документов друг за другом — это некоторое упрощение, которое намеренно используется и гарантирует корректность учета, но не является единственно возможным решением. Каждый документ в последовательности зависит не от всех предыдущих документов, а только от некоторых, например, от тех документов, в которых есть та же самая номенклатура. При этом все другие документы не требуется проводить «до» нашего выбранного документа, и их можно проводить параллельно!
Откровенно говоря, подобная идея и подход конечно не новы, например, в базе знаний фирмы «1С» по технологическим вопросам есть статья (kb.1c.ru/articleView.jsp?id=72), которая описывала подобные подходы. В интернете также можно найти и другие подобные темы, в том числе различные интерпретации таких подходов (например, «блокировочный механизм» (www.softpoint.ru/article_id375.htm и т. д.). Однако, проблемами всех указанных подходов является то, что они основываются на некоторых допущениях или искусственно формируемых «блоках» обработки данных, и не имеют четкой последовательности обработки. Мы захотели устранить эти недостатки, используя максимально «академический» подход, и считаем, нам это удалось.
Реализованный нами процесс параллельного восстановления партий состоит из двух важных этапов. Первый и ключевой этап — это расчет зависимостей документов друг от друга по специальным алгоритмам, в том числе с учетом общих прикладных допущений. Например, можно заметить, что все поступления образуют новые партии и ни от кого «до» себя не зависят, в отличие от списаний. Все такие зависимости представляются в виде графа, точками которого являются документы, а ребрами — их зависимости. Строго говоря, это ориентированный граф, но способ его обхода отличается от классических приемов и алгоритмов, поэтому нам пришлось написать свой, для которого это не важно.
Второй этап — это непосредственное восстановление (корректировка движений), только уже не по последовательности, в которой регистрируются документы платформой, а по нашему графу. При этом вот что важно — собственно код и алгоритмы формирования движений остаются полностью типовыми, а значит, конфигурация сохраняет возможность обновления. Все наши доработки находятся в отдельной подсистеме и только используют функции общих модулей, которые используются и в типовых обработках. Это гарантирует также и корректность результата — он всегда будет совпадать с типовым, последовательным восстановлением. Более того, это справедливо и для отраслевых решений (например, «1С:Управление птицефабрикой»), где в последовательности могут присутствовать специфические документы. Наличие первого этапа и дальнейший классический обход графа в глубину позволяют даже спрогнозировать и время выполнения обработки, и степень «параллельности» процесса, которая, очевидно, зависит от конкретных данных в базе. С помощью данных механизмов мы можем понять необходимые ресурсы сервера, а также эффективно управлять ими.
Собственно обработка очереди документов по такому графу не представляет собой каких‑то сложностей и достаточно типовая — есть управляющее фоновое задание, которое определяет доступные для обработки документы в нужном порядке и запускает необходимое количество рабочих фоновых заданий, каждое из которых занимается обработкой конкретного документа. Весь процесс происходит асинхронно, это значит, что для оператора нет необходимости держать открытым сеанс УПП, в котором был произведен запуск — все будет работать само, динамически отображая процесс на специальной диаграмме. Здесь же можно регулировать нагрузку — максимальное количество потоков (рабочих фоновых), которые будут запущенны одновременно. И здесь же можно даже приостановить этот процесс, поставив обработку на паузу, а также и продолжить его, без необходимости повторного расчет и запуска. Так как на первом этапе мы проводим специальные расчеты для того, чтобы быть уверенными в возможности параллельной обработки документов, в процессе обработки взаимоблокировки и таймауты блокировок практически исключены. Помешать процессу могут только параллельно работающие пользователи, которые могут только немного затормозить его, но от этого ничего не сломается и результат окажется верным в любом случае. Да, вы правильно поняли — восстанавливать последовательность можно достаточно эффективно и при работающих пользователях, главное исключить изменения данных в периоде восстановления.
Итак, проблема, казалось бы, решена, алгоритм написан, проверен и оттестирован в мельчайших деталях, однако запуск на реальной рабочей базе, начав работать в штатном режиме, стал существенно деградировать по производительности к середине обработки графа. Время обработки одного документа стало превышать 10 секунд (вместо плановых — не более секунды), и тут уже были применены стандартные подходы к оптимизации — анализ планов запросов и их оптимизация. В результате этих работ мы нашли типовой запрос в УПП, слегка переписав который можно устранить такую деградацию, при этом его результаты остаются точно такими же, как в типовом виде. Данный «патч» можно применять и при последовательном восстановлении последовательности, и при полном перепроведении документов. Можем предоставить его абсолютно бесплатно, по запросу на нашу электронную почту.
Вот теперь мы получили именно то, что планировали: многократное сокращение времени восстановления последовательности (более чем в 16 раз!), эффективная загрузка оборудования, удобные и гибкие инструменты для управления процессом. Но самое главное — это наш довольный заказчик, что для нас всегда является главной целью и наивысшей ценностью.
С отзывом совсем скоро Вы сможете ознакомиться на нашем сайте.
И напоследок, небольшой чек‑лист для Вас.
Основные приемы восстановления последовательности, от самых простых, до самых инновационных:
- Перепроведение документов для восстановления последовательности вы выполняете только в части тех документов, что используются в последовательности партионного учета и с сортировкой по моменту времени, а не по дате?
- Вместо перепроведения используете специализированный механизм восстановления партий и взаиморасчетов (в УПП и аналогичных конфигурациях)?
- Используете наше фирменное многопоточное, параллельное восстановление партий?