При анализе типовых конфигураций 1С разработчики часто сталкиваются с комбинированной настройкой регистра сведений: режим записи установлен как «Подчинение регистратору», но периодичность задана явно — например, «Секунда» или «День», а не стандартное значение «По позиции регистратора».
На первый взгляд такая схема выглядит избыточной и потенциально проблемной: если в течение одной секунды провести два документа по одним и тем же измерениям, платформа 1С выбросит исключение нарушения уникальности записей. Разберем подробно, почему разработчики платформы и типовых решений выбирают именно такую архитектуру и какие преимущества она дает на уровне СУБД.
Главная причина кроется в физической структуре таблиц и индексов, которые платформа 1С создает на сервере баз данных (MS SQL Server, PostgreSQL и др.). Проанализируем, как меняются индексы в зависимости от выбранного режима периодичности:
В этом случае основным кластерным индексом таблицы становится связка: Период + Измерения. Это оптимальная структура для выборки истории срезов. СУБД мгновенно находит актуальное состояние объекта без сканирования лишних колонок.
Так как в одну секунду могут быть записаны движения от разных документов, платформе необходимо гарантировать уникальность каждой строки. В результате кластерный индекс перестраивается в следующую структуру: Период + Регистратор + НомерСтроки. При этом во все вспомогательные индексы по измерениям также принудительно внедряется поле ссылки на документ-регистратор.
Такое раздувание индексов ссылочными типами данных приводит к существенной деградации производительности при частом чтении и росте объемов базы данных.
Рассмотрим, как СУБД выполняет запросы к виртуальным таблицам срезов при разных вариантах настройки:
Секунда) для получения актуального значения на определенную дату СУБД выполняет простую и быструю агрегацию по MAX(Период) с использованием прямого индекса по измерениям.Еще одно важное архитектурное различие заключается в управлении полем Период:
Если бизнес-логика допускает одновременное проведение нескольких документов с одинаковыми ключевыми измерениями, ошибку блокировки и неуникальности можно решить следующими практическими способами:
Период набора записей на одну секунду вперед.ДокументОснование выносят в реквизиты или измерения, а удаление движений при отмене проведения реализуют программно в модуле документа через обработчики ОбработкаПроведения и ОбработкаУдаленияПроведения.Посмотрим на пример программного контроля времени при формировании набора записей перед записью движения:
Движение = Движения.ЦеныНоменклатуры.Добавить();
Движение.Номенклатура = Выборка.Номенклатура;
Движение.Период = Дата;
// При необходимости контролируем уникальность и сдвигаем период
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| 1
|ИЗ
| РегистрСведений.ЦеныНоменклатуры КАК РС
|ГДЕ
| РС.Период = &Период
| И РС.Номенклатура = &Номенклатура
| И РС.Регистратор <> &Регистратор";
Запрос.УстановитьПараметр("Период", Движение.Период);
Запрос.УстановитьПараметр("Номенклатура", Движение.Номенклатура);
Запрос.УстановитьПараметр("Регистратор", Ссылка);
Если Не Запрос.Выполнить().Пустой() Тогда
// Сдвигаем период на секунду вперед во избежание коллизии
Движение.Период = Движение.Период + 1;
КонецЕсли;
Таким образом, использование периодичности «Секунда» для подчиненного регистратору регистра сведений — это осознанный выбор разработчиков в пользу высокой производительности запросов, компактности индексов СУБД и строгого контроля логической целостности данных.