Как оптимально спроектировать структуру регистров накопления при большом количестве измерений?

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

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

Вариант 1. Классический подход: Один регистр с множеством измерений

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

Однако при большом количестве измерений (более 10–15) мы сталкиваемся с серьезными техническими ограничениями СУБД. Каждое измерение — это поле, входящее в состав индексов. Рассмотрим, к чему это приводит:

  1. Раздувание индексов: СУБД вынуждена обновлять тяжелые индексы при каждой записи. Это замедляет проведение документов (операция INSERT в таблицы итогов и движений).
  2. Проблема селективности: Платформа строит кластерный индекс по измерениям в том порядке, в котором они указаны в конфигураторе. Если мы поставим первым измерением Организация (где всего 2 значения), а вторым — Номенклатура (где 100 000 значений), то запрос остатков только по номенклатуре будет крайне медленным, так как СУБД придется сканировать весь индекс.
  3. Блокировки: При записи в таблицу итогов SQL-сервер накладывает блокировки. Чем больше полей в индексе, тем «шире» может быть блокировка, что препятствует параллельной работе пользователей.

Этот вариант подходит только в том случае, если объем данных невелик (например, до нескольких тысяч записей в год) или если состав измерений всегда фиксирован в запросах.

Вариант 2. Механизм «Ключей аналитики» (Опыт ERP 2.0 и УТ 11)

Разберем более современный подход, который активно применяется в типовых конфигурациях последнего поколения. Вместо того чтобы создавать 20 измерений в регистре, мы создаем всего одно измерение — КлючАналитики. Это ссылка на справочник, в реквизитах которого хранятся все наши разрезы (склад, статья, подразделение и т.д.).

Как это работает на практике:

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

Рассмотрим пример кода для поиска или создания ключа аналитики:


Функция ПолучитьКлючАналитики(СтруктураПараметров)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ Ссылка 
        |ИЗ Справочник.КлючиАналитикиУчетаНоменклатуры 
        |ГДЕ Номенклатура = &Номенклатура 
        |  И Склад = &Склад 
        |  И Статья = &Статья";
    
    Запрос.УстановитьПараметр("Номенклатура", СтруктураПараметров.Номенклатура);
    Запрос.УстановитьПараметр("Склад", СтруктураПараметров.Склад);
    Запрос.УстановитьПараметр("Статья", СтруктураПараметров.Статья);
    
    Результат = Запрос.Выполнить();
    Если Не Результат.Пустой() Тогда
        Выборка = Результат.Выбрать();
        Выборка.Следующий();
        Возврат Выборка.Ссылка;
    Иначе
        НовыйКлюч = Справочники.КлючиАналитикиУчетаНоменклатуры.СоздатьЭлемент();
        ЗаполнитьЗначенияСвойств(НовыйКлюч, СтруктураПараметров);
        НовыйКлюч.Записать();
        Возврат НовыйКлюч.Ссылка;
    КонецЕсли;
    
КонецФункции

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

Недостатки: данный метод сложен в поддержке. Как отмечалось в обсуждении, обычный пользователь не понимает, что такое «Ключ аналитики», и при возникновении ошибок (например, задублировались ключи или неверно сформировались) техподдержке будет гораздо сложнее разобраться в причинах.

Вариант 3. Разделение на «Горячий» и «Холодный» контуры

Проанализируем ситуацию: действительно ли нам нужны остатки по всем 20 реквизитам? Зачастую для оперативного контроля при проведении документа нам достаточно знать остаток в разрезе Номенклатура, Склад и Характеристика. А такие данные, как Менеджер, Статья движения или Подразделение, нужны только для отчетов об оборотах за месяц.

В этом случае оптимальным решением будет создание двух регистров:

  1. Регистр остатков (Оперативный): содержит минимум измерений, необходимых для контроля (например, только Номенклатура и Склад). Это обеспечивает мгновенное проведение документа.
  2. Регистр оборотов (Аналитический): содержит все необходимые разрезы (хоть 50 измерений). Поскольку этот регистр не хранит итоги на каждую секунду (в отличие от регистра остатков), он не так сильно нагружает систему при записи и не блокирует чтение остатков другими пользователями.

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

Технические правила проектирования индексов

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

Первыми в списке измерений в конфигураторе должны идти те поля, которые:

Важный момент: Если вы создаете запрос к виртуальной таблице Остатки, всегда старайтесь передавать в параметры условия по первым измерениям регистра. Если пропустить первое измерение и наложить фильтр только по второму, платформа не сможет эффективно использовать индекс (произойдет Index Scan вместо Index Seek).

Использование «Разделения итогов»

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

Резюме и рекомендации

Подведем итог нашему анализу. Выбор структуры регистра зависит от планируемой нагрузки:

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

← На главную