Функционал ИсторияДанных позволяет сохранять историю изменения любого объекта метаданных в 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 это уже прошлое, которое будет уходить все дальше.
Теперь можно подвести некоторые итоги.
Механизм истории данных в 1С снижает производительность на 50%
Поскольку история пишется в одну таблицу по всем метаданным, то при многопоточной обработке и широком использовании в конфигурации он рано или поздно упрется в ограничения СУБД. Но для 1С это будет не так существенно поскольку параллельная запись изменений с 28 потоками в один регистр уже снижает среднюю скорость на 30-38% в независимости от включенной истории данных, поэтому Вы просто не дойдете до этой ситуации.
Механизм хорош для применений, когда изменения сильно зависят от человеческого фактора - ручной ввод. Идеален для фиксации истории изменений разных прикладных настроек на уровне базы, прав. Но если большой поток документов у Вас идет из внешней системы, то включение истории данных будет проблемой. В реализации 1С у нее просто нет запаса на маштабирование. Проблема маштабирования усугубляется процессом переноса данных из очереди изменений _datahistoryqueue0 в таблицу версий _datahistorylatestversions1 – судя по временным цифрам внутри платформы это идет последовательно. Заметьте, что для регистров накопления, хозрасчетного и расчетов историю включить нельзя – что как бы намекает на область использования данного функционала.
У кого есть решение лучше?
Собственно это вопрос к читателям. Одно дело наличие механизмов для истории данных, другое дело framework для разработки
С точки зрения улучшения данного функционала в 1С, тут путь только в сторону асинхронности и параллельности. Вообще любая задача уровня логирования несмотря на простоту постановки технически сложна. Ведь нужно это сделать незаметным для основного бизнес процесса и это не решается просто выделением вычислительных ресурсов. Просто почитайте сколько битв было при выборе основной системы логирования для Java Logging: история кошмара / Хабр
В случае истории данных ее реализация должна быть
· Асинхронной
· С высокой степенью паралеллизма. Как минимум для каждого метаданного в 1С должна быть своя таблица с историей.
· Минимальное влияние на основной бизнес процесс, в том числе при сбоях
· Маштабируемость при увеличении нагрузки. Т.е. нужна возможность выноса этого функционала на отдельные мощности и шардирование по дате.
· Удобный API для работы. Сейчас в 1С реализована только процедурная работа с историей, а язык запросов для работы с историей использовать нельзя.
Как видите реализация подобных решений непростая задача даже для крупных корпораций, и хорошо, что у 1С уже есть хороший задел в этом направлении. Рекомендую к использованию с оглядкой на ограничения по маштабированию. С прикладной точки зрения он достаточно эффективен. До новых встреч на нашем канале t.me/Chat1CUnlimited – лето будет жарким