Как правильно реализовать хранение истории изменения реквизита справочника в 1С: выбор между периодическим регистром и версионированием

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При проектировании систем на платформе 1С:Предприятие 8 часто возникает задача хранения истории изменений того или иного значения. Например, когда у элемента справочника есть реквизит (допустим, Булево), состояние которого меняется раз в месяц, и нам важно знать, какое значение было актуально в конкретный момент времени. Рассмотрим подробнее, как лучше реализовать такой механизм, проанализируем использование регистров сведений и альтернативные варианты.

Вариант 1. Периодический регистр сведений (Рекомендуемый)

Использование периодического регистра сведений — это наиболее естественный и эффективный способ для платформы 1С. В этом случае мы создаем новый объект метаданных РегистрСведений, устанавливаем для него свойство Периодичность (например, «В пределах месяца» или «День») и режим записи Независимый.

Преимущества этого подхода:

  1. Виртуальная таблица «Срез последних»: Разберем, почему это важно. Платформа «из коробки» предоставляет механизм получения наиболее актуальной записи на любую дату. Вам не нужно писать сложные вложенные запросы с использованием МАКСИМУМ(Период), достаточно обратиться к виртуальной таблице.
  2. Автоматический контроль уникальности: Платформа сама следит за тем, чтобы на одну и ту же дату (в пределах заданной периодичности) не было двух разных записей для одного и того же набора измерений.
  3. Оптимизация на уровне СУБД: В периодических регистрах поле Period автоматически включается в кластерный индекс. Это значительно ускоряет выборку данных по времени.

Проанализируем пример кода для получения текущего состояния реквизита через «Срез последних»:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ИсторияСостоянийСрезПоследних.Состояние КАК АктуальноеСостояние
    |ИЗ
    |   РегистрСведений.ИсторияСостояний.СрезПоследних(&Период, Объект = &Объект) КАК ИсторияСостоянийСрезПоследних";

Запрос.УстановитьПараметр("Период", ТекущаяДата());
Запрос.УстановитьПараметр("Объект", СсылкаНаСправочник);
Выборка = Запрос.Выполнить().Выбрать();

Вариант 2. Непериодический регистр с датой в измерениях

Иногда разработчики предпочитают создавать непериодический регистр, добавляя измерение ДатаИзменения (тип Дата) вручную. Рассмотрим ситуацию, когда это может показаться выгодным, и выясним причины, почему это не всегда оптимально.

Основной аргумент сторонников такого подхода — возможность «сделать лучше и оптимальней», чем стандартный механизм. Однако на практике это накладывает на программиста дополнительные обязанности:

Разберем пример такого «ручного» запроса:


Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |   История.Состояние
    |ИЗ
    |   РегистрСведений.ИсторияСостояний КАК История
    |ГДЕ
    |   История.Объект = &Объект
    |   И История.ДатаИзменения <= &Период
    |УПОРЯДОЧИТЬ ПО
    |   История.ДатаИзменения УБЫВ";

Такой подход допустим, но он лишает вас возможности использовать Функциональные опции, которые могут автоматически менять поведение интерфейса в зависимости от данных в периодическом регистре.

Вариант 3. Версионирование объектов (БСП)

Если в вашей конфигурации используется Библиотека стандартных подсистем (БСП), можно включить стандартную подсистему «Версионирование объектов». Это позволит хранить историю изменений вообще всех реквизитов объекта без создания новых регистров.

Но здесь есть существенные нюансы:

Оптимизация параллельной работы и блокировок

Важный технический аспект, который мы должны рассмотреть, — это вынос реквизита из справочника в регистр сведений с точки зрения блокировок СУБД. Выясним причину, почему это полезно:

Когда вы меняете реквизит непосредственно в справочнике и вызываете Объект.Записать(), платформа блокирует всю запись в таблице справочника. Если в это время другой пользователь пытается изменить, например, наименование этого же элемента, возникнет конфликт блокировок.

Использование независимого регистра сведений позволяет избежать этой проблемы. Запись в регистр блокирует только строку в таблице регистра, оставляя сам элемент справочника доступным для редактирования другими процессами. Это критически важно для высоконагруженных систем.

Режим записи: Независимый или подчиненный?

При создании регистра нужно выбрать режим записи. Посмотрим на различия:

  1. Независимый: Вы можете записывать данные программно в любой момент, используя МенеджерЗаписи. Это идеально подходит для регламентных заданий, которые раз в месяц обновляют состояние.
  2. Подчиненный регистратору: Записи в регистре могут появляться только при проведении документа. Это стоит выбрать только в том случае, если изменение состояния реквизита является юридически или финансово значимым событием (например, приказ о назначении скидки или закрытие месяца), которое должно быть подтверждено документом.

Итоги и рекомендации

Проанализировав все варианты, мы приходим к следующим выводам:

← На главную