Как правильно спроектировать регистр сведений для хранения списка объектов пользователя?

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

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

В данной статье мы подробно разберем, как правильно организовать структуру регистра для реализации «буфера обмена» объектами (например, контрагентами), проанализируем влияние уникальности записей на бизнес-логику и рассмотрим альтернативные варианты реализации этой задачи.

Измерения vs Ресурсы: Понятие уникальности ключа

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

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

Вариант 1: Одно измерение (Пользователь) и один ресурс (Контрагент)

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

  1. Для каждого конкретного пользователя в базе может существовать только одна запись.
  2. Если пользователь нажмет кнопку «Добавить в буфер» для Контрагента №1, создастся запись.
  3. Если затем он нажмет «Добавить в буфер» для Контрагента №2, система просто перезапишет ресурс в существующей записи.

Такой подход реализует связь «один-к-одному». Он удобен, если вам нужно хранить, например, «последнего выбранного контрагента», но совершенно не подходит для создания списка или «буфера».

Вариант 2: Два измерения (Пользователь и Контрагент)

В этом случае ключом записи является комбинация этих двух полей. Это позволяет реализовать связь «многие-ко-многим»:

  1. Один пользователь может добавить в список множество разных контрагентов (так как комбинации «Пользователь А + Контрагент 1» и «Пользователь А + Контрагент 2» уникальны).
  2. Один и тот же контрагент может находиться в «буферах» разных пользователей одновременно.

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

Использование свойства «Ведущее» для контроля целостности данных

При проектировании регистра сведений крайне важно обратить внимание на свойство «Ведущее» у измерений. Рассмотрим, как это работает в нашем примере с буфером:

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

Аналогично, если мы сделаем измерение Контрагент ведущим, то при удалении контрагента (или пометке на удаление с последующей очисткой) запись в буфере также исчезнет. Это предотвращает появление в интерфейсе пользователя пустых строк или сообщений об ошибке <Объект не найден>.

Производительность и индексация: Почему порядок измерений важен?

Платформа 1С автоматически создает индексы по измерениям регистра сведений. Однако эффективность этих индексов напрямую зависит от порядка следования измерений в метаданных. Разберем этот момент подробнее:

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

Если же вы сделаете Пользователя ресурсом (как предлагалось в одном из вариантов вопроса), то для получения списка объектов конкретного сотрудника системе придется выполнить полное сканирование всей таблицы регистра (Full Scan), что при большом количестве пользователей и записей приведет к существенным задержкам.

Альтернативный подход: Использование документов

В процессе обсуждения на форуме возникла интересная идея: а не использовать ли для этих целей Документ? Давайте проанализируем, в каких ситуациях это может быть оправдано.

Использование документа с табличной частью Контрагенты дает следующие преимущества:

Однако для оперативного «тыканья» в списке (быстрого добавления элементов) документ подходит меньше, так как требует постоянной записи и блокировок объекта. Регистр сведений в данном случае — более «легковесный» и быстрый инструмент.

Пример программной работы с регистром-буфером

Рассмотрим, как может выглядеть код для добавления элемента в такой регистр и последующего получения списка. Предположим, наш регистр называется БуферОбменаОбъектами с измерениями Пользователь и Объект.

Добавление записи:


МенеджерЗаписи = РегистрыСведений.БуферОбменаОбъектами.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Пользователь = ПараметрыСеанса.ТекущийПользователь;
МенеджерЗаписи.Объект = ВыбранныйКонтрагент;
// Пытаемся записать. Если такая запись уже есть, ошибки не будет, она просто обновится.
МенеджерЗаписи.Записать(Истина); 

Получение списка всех объектов пользователя через запрос:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Буфер.Объект КАК Контрагент
    |ИЗ
    |   РегистрСведений.БуферОбменаОбъектами КАК Буфер
    |ГДЕ
    |   Буфер.Пользователь = &ТекущийПользователь";

Запрос.УстановитьПараметр("ТекущийПользователь", ПараметрыСеанса.ТекущийПользователь);
РезультатЗапроса = Запрос.Выполнить();

Проблема разрастания данных и методы очистки

Поскольку регистр сведений — это физическая таблица в базе данных, данные в нем хранятся постоянно. В отличие от временных таблиц в запросах или временного хранилища (в 8.3), записи в регистре «буфера» сами не исчезнут.

Рассмотрим рекомендации по обслуживанию такого регистра:

  1. Регламентная очистка: Разумно добавить в регистр реквизит ДатаДобавления. Настройте регламентное задание, которое раз в сутки будет удалять записи, созданные более 2–3 дней назад.
  2. Очистка после обработки: Если буфер используется для формирования документов (например, счетов), предусмотрите программную очистку регистра для данного пользователя сразу после успешного выполнения операции.

Рекомендации для разных версий платформы

Выясним, как менялись подходы к реализации подобного функционала с развитием 1С:

Резюме: Если вы создаете «корзину» или «список объектов для обработки» на базе регистра сведений, делайте и Пользователя, и Объект измерениями. Это обеспечит правильную работу со списками, а установка свойства «Ведущее» и правильный порядок измерений гарантируют целостность данных и высокую скорость работы системы.

← На главную