В процессе разработки на платформе «1С:Предприятие» перед программистом часто встает архитектурная дилемма: как правильно организовать хранение данных, которые меняются во времени? Типичный пример — справочная информация (например, параметры объектов, цены, нормативы), для которой важно знать не только текущее значение, но и то, каким оно было в определенный момент в прошлом.
Рассмотрим ситуацию, когда у нас есть около 5 000 записей, и по каждой из них может вестись история изменений (иногда несколько раз в год, иногда ежедневно). В этом материале мы проанализируем два основных подхода, разберем их плюсы и минусы, а также выясним, почему профессиональное сообщество отдает предпочтение конкретному объекту метаданных.
На первый взгляд, использование справочника кажется логичным. Мы создаем объект, где в «шапке» хранятся постоянные реквизиты, а в табличной части — история изменений с датами. Однако, проанализируем технические последствия такого решения:
Регистр сведений — это специализированный объект для хранения разрезов данных. Рассмотрим, почему для нашей задачи это решение является «золотым стандартом».
Разберем преимущества использования РегистрСведений с установленной периодичностью (например, «В пределах дня» или «В пределах секунды»):
СрезПоследних и СрезПервых. Это позволяет получить актуальные данные на любую дату одним простым запросом, без необходимости вычислять максимумы вручную.Период. Это гарантирует мгновенный поиск данных именно по дате.Проанализируем ситуацию, описанную автором: необходимо выбрать данные, где дата транзакции находится между датами изменения. Если использовать регистр сведений, задача решается элегантно через СрезПоследних. Посмотрим на пример кода запроса, который выбирает данные на дату транзакции:
ВЫБРАТЬ
ИсторияДанныхСрезПоследних.Значение,
ИсторияДанныхСрезПоследних.Объект
ИЗ
РегистрСведений.ИсторияДанных.СрезПоследних(&ДатаТранзакции, Объект = &НужныйОбъект) КАК ИсторияДанныхСрезПоследних
В случае со справочником нам бы пришлось писать громоздкий вложенный запрос:
ВЫБРАТЬ
ТЧ.Значение
ИЗ
Справочник.НашСправочник.История КАК ТЧ
ГДЕ
ТЧ.Ссылка = &Ссылка
И ТЧ.ДатаИзменения = (
ВЫБРАТЬ
МАКСИМУМ(ТЧ_Внутр.ДатаИзменения)
ИЗ
Справочник.НашСправочник.История КАК ТЧ_Внутр
ГДЕ
ТЧ_Внутр.Ссылка = &Ссылка
И ТЧ_Внутр.ДатаИзменения <= &ДатаТранзакции
)
Очевидно, что первый вариант гораздо проще в поддержке и работает быстрее, так как платформа берет на себя всю сложность оптимизации на уровне СУБД.
Наиболее правильная архитектура для задачи автора выглядит следующим образом:
Ведущее позволит автоматически удалять записи регистра при удалении элемента справочника). В ресурсах регистра храним те самые изменяющиеся данные.Такой подход разделяет статические данные объекта и его динамическую историю, обеспечивая максимальную гибкость и производительность системы.
Выясним причины, по которым иногда могут возникнуть сомнения. Если данные меняются чрезвычайно часто (сотни раз в секунду), стоит обратить внимание на производительность записи в регистр. Однако для условий «несколько раз в год» или даже «раз в день» для 5 000 строк периодический регистр сведений не имеет альтернатив по эффективности.
Также стоит упомянуть механизм «История данных» (Data History), появившийся в платформе 8.3.11. Он отлично подходит для аудита изменений (кто и когда изменил поле), но для бизнес-логики и расчетов, где нужно постоянно обращаться к срезам данных, он подходит хуже, чем классический регистр сведений, так как извлечение данных из него происходит медленнее.
Для реализации задачи по хранению истории изменений однозначно выбираем периодический регистр сведений. Это обеспечит:
СрезПоследних.