Начинающие разработчики в среде 1С часто задаются вопросом: зачем нужен оборотный регистр накопления, если любые числовые данные можно сохранить в регистре сведений? Действительно, на первый взгляд оба объекта представляют собой таблицы в базе данных, способные хранить измерения и числовые ресурсы. Однако за этой внешней схожестью скрываются принципиально разные архитектурные подходы, механизмы работы СУБД, структуры хранения и возможности оптимизации производительности.
В этой статье мы подробно разберем, почему попытка заменить оборотный регистр накопления регистром сведений — это грубейшая архитектурная ошибка. Мы проанализируем внутреннее устройство этих объектов, рассмотрим реальные примеры из практики и разберем физическую структуру таблиц на уровне базы данных SQL.
Разберем фундаментальное различие в логике записи данных, которое диктует сама платформа 1С на уровне СУБД:
Период, если регистр периодический). На уровне базы данных СУБД создает уникальный индекс. Если мы попытаемся записать в регистр сведений строку с точно такими же измерениями и тем же периодом, то старая запись будет просто перезаписана новым значением (или СУБД вернет ошибку дублирования ключа). Это поведение идеально подходит для хранения цен номенклатуры, курсов валют или паспортных данных сотрудников — у одного товара в конкретную секунду может быть только одна цена.Посмотрим на наглядный пример проблемы уникальности:
Представим, что мы решили фиксировать продажи в непериодическом регистре сведений с измерениями Номенклатура и Контрагент, и ресурсом Сумма. Если покупатель "Иванов" купит "Стол" утром за 5000 рублей, а затем вечером еще один "Стол" за 5000 рублей, то при записи второй операции первая запись в регистре сведений будет затерта! Мы потеряем данные о первой продаже. Чтобы обойти это ограничение в регистре сведений, нам придется добавлять искусственные измерения (например, ссылку на документ-регистратор или уникальный идентификатор строки УникальныйИдентификатор). Но такое решение искусственно раздувает базу данных, усложняет индексы и замедляет работу всей системы.
Чтобы понять, насколько сильно отличаются эти объекты «под капотом», проанализируем структуру таблиц, которые платформа 1С создает на уровне SQL-сервера.
Физическая структура регистра сведений:
Для регистра сведений в базе данных создается всего одна основная таблица с именем вида _InfoRg<n>. В ней хранятся непосредственно сами записи. Никаких дополнительных агрегированных или итоговых таблиц для регистра сведений платформа не создает. Если нам потребуется получить обороты (сумму показателей) за период по регистру сведений, СУБД будет вынуждена динамически сканировать всю физическую таблицу, отбирать строки по периоду и группировать их на лету. На больших объемах данных это приведет к колоссальным нагрузкам и зависанию системы.
Физическая структура оборотного регистра накопления:
Для оборотного регистра накопления платформа создает как минимум две физические таблицы в SQL:
_AccumRg<n> — таблица движений. Сюда записываются детальные строки из документов-регистраторов._AccumRgTn<n> — физическая таблица итогов оборотов. Это встроенный механизм оптимизации 1С. В этой таблице платформа автоматически хранит уже рассчитанные и сгруппированные обороты в разрезе измерений с периодичностью в один месяц.Когда мы обращаемся к виртуальной таблице Обороты регистра накопления, платформа выполняет запрос не к огромной таблице движений, а к легкой таблице месячных итогов _AccumRgTn, быстро добирая остаток за неполный месяц из таблицы движений. Это обеспечивает мгновенное построение отчетов даже на базах объемом в несколько терабайт.
Разработчику в 1С доступны специализированные инструменты для работы с каждым из этих типов объектов. Сравним их возможности в запросах.
Для регистра сведений (только периодического) платформа предоставляет виртуальные таблицы СрезПоследних и СрезПервых. Попытка получить срез последних на каждую дату периода в большом регистре сведений — это классическая причина низкой производительности систем. Запрос транслируется в SQL как сложное левое соединение таблицы самой с собой с поиском максимальной даты.
Для оборотного регистра накопления доступна виртуальная таблица Обороты. Запросы к ней транслируются СУБД в простое чтение предрасчитанных итогов. Более того, для оборотных регистров накопления доступен мощнейший механизм **агрегатов** (OLAP-технологии в 1С). Разберем, как это работает:
Если в системе хранятся десятки миллионов записей о продажах, даже ежемесячных итогов может быть недостаточно для мгновенного формирования аналитической отчетности руководством. Мы можем настроить агрегаты — дополнительные таблицы, которые будут хранить готовые сгруппированные данные по наиболее популярным комбинациям разрезов (например, «Обороты по складам» или «Обороты по регионам за неделю»). Платформа сама анализирует частоту запросов пользователей, предлагает оптимальные схемы агрегации и автоматически обновляет эти таблицы при записи документов. Для регистров сведений использование агрегатов технически невозможно.
Рассмотрим реальные бизнес-задачи, где использование оборотного регистра накопления безальтернативно.
Бизнес-требование: Руководству необходим ежедневный отчет по продажам товаров в разрезе покупателей, менеджеров и складов с расчетом выручки и себестоимости.
Понятие «остаток продаж» лишено всякого смысла — мы не можем сказать «на складе осталось 10 штук продаж». Нас интересует исключительно объем совершенных операций за конкретный период (день, неделя, месяц). В этой задаче мы обязаны использовать оборотный регистр накопления (классическое имя в типовых конфигурациях — Продажи). Применение регистра сведений здесь невозможно из-за огромного потока документов, которые затирали бы записи друг друга при совпадении аналитики в рамках одной секунды, а также из-за отсутствия механизма быстрого расчета итогов.
Бизнес-требование: Анализ движения денежных средств (ДДС) по статьям движения. Нам нужно знать, сколько денег пришло по статье "Оплата от покупателей" и сколько ушло по статье "Оплата поставщикам".
Сам остаток денег на расчетных счетах хранится в регистре накопления остатков. Но для детальной классификации потоков (приход/расход) используется оборотный регистр накопления ОборотыБюджета или ДвиженияДенежныхСредств. Он позволяет строить отчеты о финансовых потоках без необходимости рассчитывать остатки на каждую дату, что существенно ускоряет работу финансового блока.
Бизнес-требование: Расчет скидки клиента в зависимости от суммы его покупок за последние 365 дней.
Для решения этой задачи отлично подойдет оборотный регистр накопления (например, НакопленныеПродажиДляСкидокКлиентам). При проведении чека или расходной накладной система делает запись в этот регистр. При расчете скидки в новом документе нам достаточно сделать один простой и быстрый запрос к виртуальной таблице Обороты за нужный интервал времени:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| НакопленныеПродажиОбороты.СуммаОборот КАК СуммаПокупок
|ИЗ
| РегистрНакопления.НакопленныеПродажиДляСкидокКлиентам.Обороты(&НачалоПериода, &КонецПериода, , Контрагент = &Контрагент) КАК НакопленныеПродажиОбороты";
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ТекущаяДата() - 365 * 24 * 60 * 60));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ТекущаяДата()));
Запрос.УстановитьПараметр("Контрагент", ТекущийКлиент);
РезультатЗапроса = Запрос.Выполнить();
Если бы мы хранили эти данные в регистре сведений, то при росте базы данных этот запрос выполнялся бы все медленнее и медленнее, вплоть до полной блокировки работы кассового узла.
Проанализируем ключевые параметры выбора между объектами метаданных и обобщим их в удобном виде:
Регистр сведений: Свойства, настройки, состояния, курсы, тарифы, паспортные данные, цены.Оборотный регистр накопления: Потоки событий, продажи, затраты, объемы услуг, звонки, клики, транзакции.Регистр сведений: Строго уникален по комбинации измерений (+ период). Новая запись перезаписывает старую.Оборотный регистр накопления: Не уникален. Любое количество записей по одинаковым измерениям суммируется.Регистр сведений: Любой тип данных (Число, Строка, Булево, СправочникСсылка, ДокументСсылка).Оборотный регистр накопления: Только числовые типы (так как данные складываются и вычитаются).Регистр сведений: Отсутствуют. Расчет итогов производится динамически при каждом запросе.Оборотный регистр накопления: Автоматический расчет ежемесячных итогов + возможность создания ручных и автоматических агрегатов.Подводя итог, можно сказать: всегда используйте инструменты платформы 1С по их прямому назначению. Не пытайтесь эмулировать оборотные механизмы на регистрах сведений. Понимание разницы в физической структуре таблиц SQL, механизмах расчета итогов и логике уникальности записей позволяет проектировать высокопроизводительные системы, которые будут работать быстро и стабильно даже при многократном росте объема базы данных.