При работе с платформой 1С:Предприятие 7.7 разработчики часто сталкиваются с проблемой низкой производительности при записи большого количества данных. Типичная ситуация: необходимо перенести 5000 или более строк из табличной части документа в подчиненный справочник. Стандартный перебор строк с созданием нового объекта и вызовом метода Записать() может занимать неприемлемо много времени. В этой статье мы подробно разберем, почему это происходит и как ускорить процесс в десятки раз.
Для начала проанализируем, как работает стандартный механизм записи объекта в 1С 7.7. Когда мы вызываем метод Записать(), система выполняет целый ряд ресурсоемких операций:
Если мы выполняем эти действия 5000 раз подряд в цикле, каждое из них инициирует отдельное обращение к файловой системе или серверу SQL, что создает «бутылочное горлышко» ввода-вывода.
Самый эффективный встроенный способ ускорения — использование механизмов НачатьТранзакцию() и ЗафиксироватьТранзакцию(). Транзакция позволяет объединить множество операций записи в один блок. Система накапливает изменения в памяти и записывает их на диск одним массивом при завершении транзакции.
Рассмотрим правильную реализацию пакетной записи. Опытным путем установлено, что фиксация транзакции каждые 500–1000 элементов является оптимальной, так как слишком большая транзакция может переполнить лог транзакций SQL или вызвать длительную блокировку базы для других пользователей.
Разберем программный код для реализации этого метода:
Процедура ЗагрузкаВСправочник()
Перем Счетчик;
Счетчик = 0;
// Создаем объект справочника один раз вне цикла
ХранилищеКодов = СоздатьОбъект("Справочник.ХранилищеКодов");
// Открываем первую транзакцию
НачатьТранзакцию();
ВыбратьСтроки();
Пока ПолучитьСтроку() = 1 Цикл
Счетчик = Счетчик + 1;
ХранилищеКодов.Новый();
// Установка владельца напрямую через атрибут быстрее, чем ИспользоватьВладельца()
ХранилищеКодов.Владелец = ТекущийДокумент();
ХранилищеКодов.КодМ = КодыМ; // Предполагается, что КодыМ — это реквизит строки документа
ХранилищеКодов.Состояние = 0;
ХранилищеКодов.Записать();
// Пакетная фиксация каждые 500 итераций
Если Счетчик % 500 = 0 Тогда
ЗафиксироватьТранзакцию();
НачатьТранзакцию();
КонецЕсли;
КонецЦикла;
// Фиксируем остаток записей
ЗафиксироватьТранзакцию();
Сообщить("Загрузка завершена успешно!");
КонецПроцедуры
Обратите внимание на использование оператора % (остаток от деления) для проверки кратности счетчика. Это позволяет элегантно управлять размером пакета данных.
Проанализируем структуру самого справочника ХранилищеКодов. Если бизнес-логика позволяет, можно внести изменения в конфигураторе, которые существенно ускорят запись:
Код не несет смысловой нагрузки, установите его длину в 0. Это избавит систему от необходимости проверять уникальность и обновлять индекс по коду при каждой записи.Выясним причину, по которой использование метода ИспользоватьВладельца() может быть менее эффективным внутри цикла. Метод ИспользоватьВладельца() предназначен в первую очередь для фильтрации выборки в формах списков. При программном создании новых элементов в подчиненном справочнике гораздо быстрее и надежнее напрямую присваивать значение атрибуту Владелец.
Сравним два подхода:
Медленно:
ХранилищеКодов.ИспользоватьВладельца(НужныйВладелец); — это заставляет объект перенастраивать свои внутренние фильтры.
Быстро:
ХранилищеКодов.Владелец = НужныйВладелец; — это прямая запись в реквизит объекта.
Проанализируем ситуацию: зачем нам вообще дублировать 5000 строк из документа в отдельный справочник? В среде 1С 7.7 часто используют подчиненные справочники как аналог «Регистров сведений» из восьмой версии платформы. Однако, если эти данные нужны только для чтения или последующих отчетов, стоит рассмотреть альтернативы:
1C++ позволит записать все 5000 строк одним SQL-запросом INSERT INTO. Это самый быстрый способ из существующих (занимает доли секунды).Документ, не перегружая базу данных лишними записями в справочниках.При выполнении массовых операций в 1С 7.7 крайне важно учитывать среду исполнения. Посмотрим на важные нюансы:
Монопольный режим: Если процедура выполняется в монопольном режиме, скорость записи возрастает в разы, так как система отключает механизмы управления блокировками файлов (в DBF) или оптимизирует работу с кэшем индексов.
Отключение визуального обновления: Если во время работы обработки у пользователей открыты формы списков изменяемого справочника, система будет тратить время на рассылку оповещений (Notify) об обновлении данных. Для максимальной скорости такие массовые загрузки рекомендуется проводить в периоды минимальной активности пользователей.
Использование Таблицы Значений: Перед началом записи рекомендуется выгрузить данные из документа в объект ТаблицаЗначений. Чтение данных из оперативной памяти (из таблицы значений) происходит быстрее, чем постоянное обращение к строкам многострочной части документа через ПолучитьСтроку(), особенно если документ содержит очень много реквизитов.
Таким образом, сочетание пакетных транзакций, правильной настройки метаданных и грамотного обращения с атрибутами объекта позволяет превратить мучительно долгий процесс записи в быструю и эффективную операцию.