Как ускорить 1С – Многопоточная обработка данных

17.10.14

База данных - HighLoad оптимизация

Чем будет для Вас полезна эта статья:

• Вы изучите варианты ускорения операций обработки данных
• Научитесь запускать в «1С:Предприятие 8» несколько потоков
• Узнаете об ограничениях многопоточного режима в 1С

Файлы

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование Скачано Купить файл
Как ускорить 1С – Многопоточная обработка данных
.pdf 492,01Kb
20 1 850 руб. Купить
Multitasking.zip
.zip 169,31Kb
18 1 850 руб. Купить

Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний

Оформите подписку на компанию для решения рабочих задач

Оформить подписку и скачать решение со скидкой

 

Периодически возникает необходимость в ускорении некоторых участков кода, в которых при беглом ознакомлении нет потенциала для ускорения.

Рассмотрим в качестве примера выгрузку и/или загрузку большого количества данных.

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

Не все знают, что в платформе «1С: Предприятие 8» часть операций можно выполнять параллельно, путем одновременного выполнения в несколько потоков.

Такая многопоточная обработка вполне применима в случае, когда нужно обработать независимые блоки данных. В частности, создать большой объем элементов данных, осуществить проведение документов, не пересекающихся по значениям набора измерений, сделать массовое обновление элементов справочников, выполнить загрузку данных в регистры и т.д. Для примера рассмотрим задачу: необходимо провести обновление реквизита «Цена» для всех элементов справочника «Товары». Количество элементов справочника «Товары» равно 100 000. Самым простым и очевидным решением выступает нижеприведенный код обработки, который быстро пишется, но при этом очень долго работает: 

 

&НаСервере

Процедура ОбновитьЦену()

ВремяНачала = ТекущаяДата();


Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Товары.Ссылка

|ИЗ

| Справочник.Товары КАК Товары";


ТаблицаТоваров = Запрос.Выполнить().Выгрузить();


Наценка = 1.10;


Для каждого ТекСторока Из ТаблицаТоваров Цикл

ТоварОбъект = ТекСторока.Ссылка.ПолучитьОбъект();

ТоварОбъект.Цена = ТоварОбъект.Цена*Наценка;

ТоварОбъект.Записать();

КонецЦикла;


Длительность = ТекущаяДата()-ВремяНачала;


Сообщить("Длительность: " + Длительность + " сек.");


КонецПроцедуры

 

В нашем случае обработка выполнялась 1 187 секунд или 19,7 минуты. Теперь воспользуемся многопоточным выполнением программного кода. Перепишем код обработки следующим образом: 


&НаСервере

Процедура ОбновитьЦену()


ВремяНачала = ТекущаяДата();


Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Товары.Ссылка

|ИЗ

| Справочник.Товары КАК Товары";

ТаблицаТоваров = Запрос.Выполнить().Выгрузить();


// определяем максимальное количество потоков

ЧислоПотоков = 8;


ЧислоСтрокВТаблице = ТаблицаТоваров.Количество();


// объем порции данных для обработки каждым потоком

РазмерПорции = Цел(ЧислоСтрокаВТаблице/ЧислоПотоков);


// массив, где будут храниться фоновые задания

МассивЗаданий = НовыйМассив;


Для НомерПотока = 1 По ЧислоПотоков Цикл


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

// разные потоки обрабатывают разные части таблицы

ИндексНачала = (НомерПотока - 1)*РазмерПорции;


Если (НомерПотока = ЧислоПотоков) Тогда

// если это последний поток, то он обрабатывает все оставшиеся данные

// т.к. число потоков может не быть кратно количеству строк в таблице

РазмерПорции = ЧислоСтрокВТаблице -(ЧислоПотоков*РазмерПорции)+РазмерПорции;

КонецЕсли;


// определяем массив параметров для процедуры

НаборПараметров = Новый Массив;

НаборПараметров.Добавить(ТаблицаТоваров);

НаборПараметров.Добавить(ИндексНачала);

НаборПараметров.Добавить(РазмерПорции);


// запуск фонового задания

Задание = ФоновыеЗадания.Выполнить("ОбщийМодуль1.ОбновитьЦенуТовара", НаборПараметров);


// добавляем задание в массив, чтобы потом отследить выполнение

МассивЗаданий.Добавить(Задание);


КонецЦикла;


// проверим результат выполнения фоновых заданий

Если МассивЗаданий.Количество() > 0 Тогда

Попытка

ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданий);

Исключение

// действия в случае ошибки

КонецПопытки;

КонецЕсли;


Длительность = ТекущаяДата()-ВремяНачала;


Сообщить("Длительность: " + Длительность + "сек.");


КонецПроцедуры

 

Процедура ОбновитьЦенуТовара (ТаблицаТоваров,ИндексНачала,РазмерПорции) Экспорт


Наценка = 1.10; // наценка 10%


// обновляем цену только для определенной части таблицы

Для Сч = 1 По РазмерПорцииЦикл

Индекс = ?(Сч=1,ИндексНачала,Индекс+1);

ТоварОбъект = ТаблицаТоваров[Индекс].Ссылка.ПолучитьОбъект();

ТоварОбъект.Цена = ТоварОбъект.Цена * Наценка;

ТоварОбъект.Записать();

КонецЦикла;

КонецПроцедуры

 

В нашем случае использовалось восемь потоков, обновление цен было выполнено за 859 секунд или 14,3 минуты.

То есть обработка одной и той же Таблицы Значений параллельно разными потоками приводит к выигрышу в скорости.

Код выполнялся на виртуальной машине с одним процессором без RAID массивов. На реальном и хорошем «железе» выигрыш в скорости будет существенно больше.

Заметим, что данную задачу можно решить по-другому, мы привели лишь один пример реализации.

Важно! Не нужно устанавливать слишком большое количество потоков, так как большого прироста скорости вы от этого все равно не получите, а стабильность работы может нарушиться.

Наилучшим будет использование 8-10 потоков, а их оптимальное количество можно определить экспериментально. Попробуйте самостоятельно провести эксперимент, база и обработки в приложении к статье.

 


 Бурмистров Андрей

 

Другие полезные статьи и видео смотрите на нашем сайте: http://

Вступайте в нашу телеграмм-группу Инфостарт

Ускорение Производительность Запросы Оптимизация Курсы Обучение Курсы-по-1С.рф Гилев Насипов Spec8.ru Spec8 NasF

См. также

HighLoad оптимизация Программист 1C:ERP Бесплатно (free)

Использование оператора «В» для полей или данных составного типа (например, Регистратор) может приводить к неочевидным проблемам.

10.11.2025    5661    ivanov660    48    

51

HighLoad оптимизация Программист 1С:Предприятие 8 1C:ERP Бесплатно (free)

Приведем примеры использования различных в динамических списках и посмотрим, почему это плохо.

18.02.2025    8390    ivanov660    39    

61

HighLoad оптимизация Технологический журнал Системный администратор Программист Бесплатно (free)

Обсудим поиск и разбор причин длительных серверных вызовов CALL, SCALL.

24.06.2024    10780    ivanov660    13    

64

HighLoad оптимизация Программист 1С:Предприятие 8 Бесплатно (free)

Метод очень медленно работает, когда параметр приемник содержит намного меньше свойств, чем источник.

06.06.2024    16801    Evg-Lylyk    73    

46

HighLoad оптимизация Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Анализ простого плана запроса. Оптимизация нагрузки на ЦП сервера СУБД используя типовые индексы.

13.03.2024    8297    spyke    29    

54

HighLoad оптимизация Программист 1С:Предприятие 8 Бесплатно (free)

Оказывается, в типовых конфигурациях 1С есть, что улучшить!

13.03.2024    11641    vasilev2015    22    

47