Найти в Дзене
1CUnlimited

История изменений или изменения с историей.

Функционал ИсторияДанных позволяет сохранять историю изменения любого объекта метаданных в 1С с любым удобным набором реквизитов. Это позволяет решать многие задачи учета и отказаться от сложных логов. Но у любого избыточного хранения данных есть цена. На простом нагрузочном тесте мы поймем какова цена для 1С. Если у Вас решение на другой платформе, но с похожей структурой данных то Вы сможете оценить границы возможного и для себя. В базе с большим числом пользователей, и объемами – два извечных вопроса «Кто виноват? » @Герцен «Что делать?» @Чернышевский Актуальны всегда. Логирование решает вопрос ограниченно, поскольку фиксирует только определенные события, а что было изменено это уже сложнее. Еще актуален вопрос, корректного перепроведения чего либо при изменениях в прошлом периоде. Например, прошлый период закрыт для проводок, но в текущем нужно сделать грамотные сторно, в зависимости от того какие реквизиты поменялись. На это влияют ключевые реквизиты – которые влияют на суммы, или
Оглавление
История изменений скоро будет неподьемной
История изменений скоро будет неподьемной

Функционал ИсторияДанных позволяет сохранять историю изменения любого объекта метаданных в 1С с любым удобным набором реквизитов. Это позволяет решать многие задачи учета и отказаться от сложных логов. Но у любого избыточного хранения данных есть цена. На простом нагрузочном тесте мы поймем какова цена для 1С. Если у Вас решение на другой платформе, но с похожей структурой данных то Вы сможете оценить границы возможного и для себя.

Зачем нужна история данных?

В базе с большим числом пользователей, и объемами – два извечных вопроса

«Кто виноват? » @Герцен «Что делать?» @Чернышевский

Актуальны всегда. Логирование решает вопрос ограниченно, поскольку фиксирует только определенные события, а что было изменено это уже сложнее.

Еще актуален вопрос, корректного перепроведения чего либо при изменениях в прошлом периоде. Например, прошлый период закрыт для проводок, но в текущем нужно сделать грамотные сторно, в зависимости от того какие реквизиты поменялись. На это влияют ключевые реквизиты – которые влияют на суммы, или аналитика.

Так же историю данных можно использовать как триггер для разных событий, например, предоставление нового уровня скидки клиенту в зависимости от купленных или заказанных товаров.

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

В целом вариантов использования истории данных много

Архитектурная эволюция решения этих вопросов как правило выглядит так

· Сначала логгируют все что можно, до тех пор пока логи читать невозможно.

· Потом прикручивают разные средства типа Elastic search , и ждут пока стоимость логирования превысит их пользу

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

· И высшая стадия эволюции – работать не с документами и операциями, а с версиями (правда это не тема данной статьи вот тут есть пример Язык мой – враг мой. Архитектору о будущем 1С) . Там правда сразу вылезают другие проблемы типа перманентной уборки мусора, но зато нет других проблем.

Если посмотреть шире – есть архитектурный термин Slowly changing dimensions (SCD), где история данных 1С это частный случай Как медленно меняющиеся измерения помогают сохранить контекст изменений в данных / Хабр . В данной классификации SCD тип 5

Архитектура истории данных в 1С.

Механизм ИсторииДанных в 1С подробно описан тут Глава 25. История данных :: Руководство разработчика :: 1С:Предприятие 8.3.27. Документация . Идея механизма кратко и хорошо изложена тут История данных | 1С:Зазеркалье

Ниже я сжато изложу работу на основе внутренних таблиц 1С

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

Для эксперимента включим историю данных в регистре

Включаем историю изменения
Включаем историю изменения

В регистре фиксацию истории данных можно включить для отдельных реквизитов. Измерения не имеют данного признака поскольку включаются по-умолчанию.

Включаем историю в реквизитах
Включаем историю в реквизитах

С точки зрения внутренней структуры история данных это набор таблиц. Для понимания – включим ведение истории данных в регистре котировок и сделаем два изменения.

Как история данных огранизована на таблицах
Как история данных огранизована на таблицах

Видно, что сначала они накапливаются в _datahistoryqueue0

Если открыть меню версий в платформе, то мы увидим только одну. Это сработал механизм платформы – он перенес последнюю версию из таблицы queue в datahistoryhistory и datahistorylatestversions

Для переноса всех накопленных версий нужно вызвать программный метод ИсторияДанных.ОбновитьИсторию(ДляМетаданных,Неопределено,Ложь,Истина);

Есть важные нюансы. Например, когда меняешь данные регистра сведений через интерфейс платформы\или в режиме замещения – сначала фиксируется удаление, потом добавление новой версии. Это особенность платформы.

История данных по регистру сведений
История данных по регистру сведений

Версии можно сравнить стандартным отчетом платформы. Есть ограничение – нельзя сравнивать удаленную версию с какой-либо другой. Поэтому, при начале работы с версиями нужно зафиксировать начальные версии с помощью метода ЗаписатьВерсию()

Механизм платформы
Механизм платформы

В таблице версий информация хранится в большей степени в бинарном виде, а не в отдельных полях. Это означает, что работа с версиями может производится только с помощью стандартных методов 1С. Бинарное хранение сделано из – за универсальности решения. Таблица одна для всех видов метаданных, об эффективности такого решения поговорим позже

Таблица очереди истории данных
Таблица очереди истории данных

В платформенном интерфейсе есть также недостатки. Например, при изменении значения Периода в регистре сведений, типовым способом посмотреть историю не получится. Поскольку фильтры и отбор в проверке истории устанавливается по текущей записи.

Что будет при изменении измерения
Что будет при изменении измерения

На первый взгляд ошибка, но поле Период ключевое для отбора по Регистру и это не ссылка на Документ, которая не может меняться. А Регистры сведений по сути таблицы с уникальными индексами и constraints по ключевым полям – у них нет уникального ИД записи. Поэтому, когда меняются ключевые поля, сопоставить историю записей с разными ключевыми полям можно только в своем отчете и не во всех прикладных случаях.

Насколько просядет производительность.

Если анализировать с точки зрения архитектора Сколько точек зрения у Архитектора в ИТ? то сразу бросается в глаза узкое место

1) Таблица очереди для истории данных _datahistoryqueue0 одна на все метаданные

2) В ней два индекса, что как минимум будет влиять на скорость вставки данных

Индексы истории данных
Индексы истории данных

Поэтому мы сделаем тест на регистре сведений СУУ_РыночныеКотировки сначала без истории данных, а потом с историей данных (в историю включены все реквизиты для усложнения теста)

Результаты сведены в таблицу ниже. Обработку для теста можно скачать Обработка тест истории изменений отчеты по тесту можно посмотреть Подробные результаты тестов

Тест многопотоковый (фоновые задания) изменяет записи в регистре сведений, для каждого потока вычисляется средняя скорость обновления записи (меняем пару реквизитов). Сервер 1С 8.3.23.1739 + Postgres на двухпроцессорном сервере с SSD

Результат тестов истории данных
Результат тестов истории данных

Без истории данных средняя скорость 149, а с включенной историей 77. Т.е. 50% падения производительности это цена за запись истории в таблицу очереди _datahistoryqueue0 . Она включает в себя сериализацию данных и расходы на запись в СУБД.

А теперь увеличим количество потоков до 28 – в нашем тесте это перезапись котировок за разные дни т.е. пересечения по обновляемым записям нет.

Без включенной истории средняя скорость 103 записи в секунду на поток, а с историей 48 записей в секунду на поток. За счет конкурентности записи в одну таблицу скорость снизилась на 30-38% в обоих случаях. Однако поскольку проценты снижения скорости одинаковы это означает, что узким местом тут уже является СУБД (в данном случае Postgres) а не кластер 1С. Под узким местом я понимаю не только процесс записи в СУБД истории данных, но и запись с замещением в регистр сведений – там сложнее набор DML что видно ниже

Загрузка процессора показывает высокую параллельность формирования DML запросов к СУБД по истории данных

Нагрузка процессора в истории данных
Нагрузка процессора в истории данных

Если посмотреть, какие DML операции занимают время, то это хорошо знакомый из других тестов Fastruncate для временных таблиц Postgres как предчувствие. Вычисляем процент импортозамещения в режиме Highload от 1С / Хабр. Это больное место Postgres, возможно в MS SQL, Oracle результаты будут другими, однако в России MS SQL это уже прошлое, которое будет уходить все дальше.

Что больше занимает времени - Fasttruncate
Что больше занимает времени - Fasttruncate

Теперь можно подвести некоторые итоги.

Механизм истории данных в 1С снижает производительность на 50%

Поскольку история пишется в одну таблицу по всем метаданным, то при многопоточной обработке и широком использовании в конфигурации он рано или поздно упрется в ограничения СУБД. Но для 1С это будет не так существенно поскольку параллельная запись изменений с 28 потоками в один регистр уже снижает среднюю скорость на 30-38% в независимости от включенной истории данных, поэтому Вы просто не дойдете до этой ситуации.

Механизм хорош для применений, когда изменения сильно зависят от человеческого фактора - ручной ввод. Идеален для фиксации истории изменений разных прикладных настроек на уровне базы, прав. Но если большой поток документов у Вас идет из внешней системы, то включение истории данных будет проблемой. В реализации 1С у нее просто нет запаса на маштабирование. Проблема маштабирования усугубляется процессом переноса данных из очереди изменений _datahistoryqueue0 в таблицу версий _datahistorylatestversions1 – судя по временным цифрам внутри платформы это идет последовательно. Заметьте, что для регистров накопления, хозрасчетного и расчетов историю включить нельзя – что как бы намекает на область использования данного функционала.

У кого есть решение лучше?

Собственно это вопрос к читателям. Одно дело наличие механизмов для истории данных, другое дело framework для разработки

С точки зрения улучшения данного функционала в 1С, тут путь только в сторону асинхронности и параллельности. Вообще любая задача уровня логирования несмотря на простоту постановки технически сложна. Ведь нужно это сделать незаметным для основного бизнес процесса и это не решается просто выделением вычислительных ресурсов. Просто почитайте сколько битв было при выборе основной системы логирования для Java Logging: история кошмара / Хабр

В случае истории данных ее реализация должна быть

· Асинхронной

· С высокой степенью паралеллизма. Как минимум для каждого метаданного в 1С должна быть своя таблица с историей.

· Минимальное влияние на основной бизнес процесс, в том числе при сбоях

· Маштабируемость при увеличении нагрузки. Т.е. нужна возможность выноса этого функционала на отдельные мощности и шардирование по дате.

· Удобный API для работы. Сейчас в 1С реализована только процедурная работа с историей, а язык запросов для работы с историей использовать нельзя.

Как видите реализация подобных решений непростая задача даже для крупных корпораций, и хорошо, что у 1С уже есть хороший задел в этом направлении. Рекомендую к использованию с оглядкой на ограничения по маштабированию. С прикладной точки зрения он достаточно эффективен. До новых встреч на нашем канале t.me/Chat1CUnlimited – лето будет жарким