При разработке конфигураций на платформе 1С:Предприятие 8.3 мы часто сталкиваемся с задачами обработки больших массивов данных в памяти. Одним из наиболее эффективных инструментов является ТаблицаЗначений. Однако начиная с версии платформы 8.3.11, многие разработчики заметили существенное снижение производительности методов Свернуть и Индексы.Добавить. Давайте разберемся, почему это происходит и как мы можем оптимизировать наш код.
В ходе наших тестов мы выяснили, что проблема не связана с прямыми обращениями к базе данных. Профилировщик показывает, что задержки возникают внутри самого ядра платформы при обработке колонок ссылочного типа. Когда мы работаем со ссылками на справочники или другие объекты, платформа, по-видимому, пытается произвести дополнительные манипуляции (например, привести типы или подготовить данные для представления), что создает колоссальную нагрузку на ресурсы процессора и оперативной памяти.
Важно отметить, что проблема проявляется только для «реальных» ссылок, полученных из базы данных. Если мы заполняем таблицу ссылками, созданными программно через ПолучитьСсылку с использованием новых УникальныйИдентификатор, деградации производительности не наблюдается. Это подтверждает гипотезу о том, что платформа некорректно обрабатывает метаданные или кэшированные свойства, связанные с объектами, считанными из ИБ.
Если нам критически важна скорость выполнения операций, мы можем пойти по пути «развязки» данных. Вместо того чтобы хранить в колонке саму ссылку, давайте разобьем эту информацию на две составляющие: УникальныйИдентификатор (как строку или GUID) и, при необходимости, данные о типе. Свертка по таким примитивным типам происходит практически мгновенно.
Рассмотрим пример того, как мы можем подготовить данные перед сверткой:
// Вместо хранения ссылки напрямую, разделяем ее на составляющие
ТаблицаДляСвертки = Новый ТаблицаЗначений;
ТаблицаДляСвертки.Колонки.Добавить(\"ТипСсылка\", Новый ОписаниеТипов(\"Строка\"));
ТаблицаДляСвертки.Колонки.Добавить(\"UID\", Новый ОписаниеТипов(\"Строка\"));
Для Каждого Стр Из ИсходнаяТаблица Цикл
НоваяСтрока = ТаблицаДляСвертки.Добавить();
НоваяСтрока.ТипСсылка = ТипЗнч(Стр.ПолеСсылка);
НоваяСтрока.UID = Строка(Стр.ПолеСсылка.УникальныйИдентификатор());
КонецЦикла;
// Теперь свертка пройдет очень быстро
ТаблицаДляСвертки.Свернуть(\"ТипСсылка, UID\");
После выполнения свертки мы всегда можем восстановить ссылочный тип, используя Справочники.ИмяСправочника.ПолучитьСсылку() и переданный УникальныйИдентификатор.
В тех случаях, когда наша основная цель — получить уникальный список элементов, вместо ТаблицаЗначений рекомендуется использовать Соответствие. Метод работы с хэш-таблицами внутри Соответствие не подвержен той же деградации производительности, что и методы таблиц значений, даже при работе с объектными типами.
Рассмотрим пример использования:
СоответствиеУникальных = Новый Соответствие;
Для Каждого Стр Из ИсходнаяТаблица Цикл
// Используем ссылку как ключ
СоответствиеУникальных.Вставить(Стр.ПолеСсылка, Истина);
КонецЦикла;
// В результате в Соответствие у нас остались только уникальные ссылки
Для Каждого КлючИЗначение Из СоответствиеУникальных Цикл
УникальнаяСсылка = КлючИЗначение.Ключ;
КонецЦикла;
Свертка или Индексация, особенно при наличии в таблице ссылочных типов.Подводя итог, можно сказать, что хотя архитектурные изменения в платформе 8.3.11+ привели к временным трудностям, понимание того, как именно 1С работает со ссылками и представлениями, позволяет нам находить эффективные обходные пути. Мы надеемся, что эти рекомендации помогут вам ускорить работу ваших алгоритмов обработки данных.