Как эффективнее обрабатывать рабочие интервалы сотрудников: таблица в таблице или одна общая таблица значений

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

При разработке механизмов планирования ресурсов, особенно в таких конфигурациях как 1С:Управление нашей фирмой (УНФ), программисты часто сталкиваются с задачей обработки больших массивов временных интервалов. Основной вопрос заключается в выборе структуры данных: хранить ли интервалы каждого сотрудника в отдельной вложенной ТаблицеЗначений или использовать одну плоскую таблицу для всех данных. Разберем подробно каждый подход, их плюсы, минусы и влияние на производительность системы.

Вариант 1: Иерархическая структура (ТЗ внутри другой ТЗ)

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

Проанализируем особенности этого подхода:

Вариант 2: Плоская индексированная Таблица Значений

Это более универсальный и производительный метод. Мы создаем одну таблицу с колонками Сотрудник, ДатаНачала, ДатаОкончания и другими необходимыми реквизитами.

Рассмотрим, как правильно организовать работу с такой таблицей:

  1. Индексация: Для быстрого поиска необходимо использовать метод Индексировать(). Если мы планируем искать данные по сотруднику, колонка Сотрудник должна быть включена в индекс.
  2. Поиск данных: Вместо полного перебора используем метод НайтиСтроки(). При наличии индекса этот метод работает со скоростью, близкой к бинарному поиску.

Пример подготовки такой таблицы:


ТЗИнтервалы = Новый ТаблицаЗначений;
ТЗИнтервалы.Колонки.Добавить("Сотрудник", Новый ОписаниеТипов("СправочникСсылка.Сотрудники"));
ТЗИнтервалы.Колонки.Добавить("ДатаНачала", Новый ОписаниеТипов("Дата"));
ТЗИнтервалы.Колонки.Добавить("ДатаОкончания", Новый ОписаниеТипов("Дата"));
ТЗИнтервалы.Колонки.Добавить("НомерСтроки", Новый ОписаниеТипов("Число")); // Для сохранения сортировки

// Заполнение данными...
ТЗИнтервалы.Индексы.Добавить("Сотрудник");

Важный нюанс по сортировке: Чтобы гарантированно сохранить исходный порядок данных (Stable Sort), обязательно добавляйте колонку НомерСтроки. Метод Сортировать() в 1С не всегда сохраняет относительный порядок равных элементов, и наличие числового индекса строки — единственный надежный способ восстановить последовательность.

Вариант 3: Использование соответствий (Объект Соответствие)

Выясним, почему многие разработчики предпочитают Соответствие (Map) вместо поиска в ТЗ. Доступ к значению по ключу в Соответствии осуществляется через хеш-таблицу, что теоретически быстрее (O(1)), чем поиск в индексированной таблице (O(log n)).

Мы можем скомбинировать подходы: использовать Соответствие, где ключом будет Сотрудник, а значением — массив строк из общей таблицы или даже подмножество данных. Это позволяет мгновенно переключаться между контекстами разных сотрудников в сложном алгоритме заполнения ресурсов.

Вариант 4: Обработка данных через временные таблицы в запросе

Если данных действительно много, лучшим решением будет перенос логики на сторону СУБД. Посмотрим на пример использования временных таблиц для поиска нужного интервала:


МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;

// Выгружаем ТЗ во временную таблицу
Запрос.Текст = "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Интервалы ИЗ &ТЗИнтервалы КАК ТЗИнтервалы";
Запрос.УстановитьПараметр("ТЗИнтервалы", ТЗИнтервалы);
Запрос.Выполнить();

// Теперь можем эффективно выбирать данные
Запрос.Текст = 
"ВЫБРАТЬ
|	ВТ.ДатаНачала,
|	ВТ.ДатаОкончания
|ИЗ
|	ВТ_Интервалы КАК ВТ
|ГДЕ
|	ВТ.Сотрудник = &ЗаданныйСотрудник
|	И &НужнаяДата МЕЖДУ ВТ.ДатаНачала И ВТ.ДатаОкончания";

Проанализируем этот метод: использование запроса позволяет выполнять интервальный поиск (условия "больше", "меньше", "между"), который в обычной ТаблицеЗначений через НайтиСтроки() реализовать невозможно (он ищет только по точному равенству). Однако помните, что выполнение запроса внутри цикла — это всегда потеря производительности из-за вызовов сервера приложений и СУБД.

Специфика планирования ресурсов в УНФ

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

Рекомендуется следующий алгоритм:

  1. Одним запросом получить все базовые данные (графики, исключения, записи о рабочем времени) во временные таблицы.
  2. В запросе выполнить соединение этих таблиц, чтобы получить плоскую структуру "период — доступность".
  3. Выгрузить результат в одну общую ТаблицуЗначений с индексом по сотруднику и дате.
  4. При обходе в коде использовать алгоритм "прерывания": сортируем таблицу по сотруднику и дате, идем одним циклом и отслеживаем момент, когда значение в колонке Сотрудник меняется. Это гораздо быстрее, чем многократные поиски.

Итоги и рекомендации

Подведем итоги нашего анализа:

Рассмотренные методы позволяют оптимизировать заполнение документов "Загрузка ресурсов" или расчет графиков, избегая лишних обращений к базе данных и экономя ресурсы сервера.

← На главную