A1sCode библиотека 1С

Зачем пакетировать

Два паттерна: батчинг списков (IN) и параметры-таблицы (&ВТ).

Паттерн 1 — батчинг списков (IN &Список)

Делим большой массив ссылок на чанки по 200–1000 элементов и вытягиваем данные порциями.

Утилита: разбиение массива на чанки


Функция РазбитьНаЧанки(ИсхМассив, РазмерЧанка) Экспорт
    Рез = Новый Массив;
    Если РазмерЧанка <= 0 Тогда Возврат Рез; КонецЕсли;
    Тек = Новый Массив;
    Для каждого Э Из ИсхМассив Цикл
        Тек.Добавить(Э);
        Если Тек.Количество() >= РазмерЧанка Тогда
            Рез.Добавить(Тек);
            Тек = Новый Массив;
        КонецЕсли;
    КонецЦикла;
    Если Тек.Количество() > 0 Тогда Рез.Добавить(Тек); КонецЕсли;
    Возврат Рез;
КонецФункции
      

Выгрузка по ID батчами


Функция НомПоIDБатчами(IDsМассив, РазмерЧанка = 500) Экспорт
    ТекстQ = "
    |ВЫБРАТЬ
    |    Ном.Ссылка       КАК ID,
    |    Ном.Наименование КАК Name
    |ИЗ Справочник.Номенклатура КАК Ном
    |ГДЕ Ном.Ссылка В (&Список)
    ";
    Результ = Новый ТаблицаЗначений;
    Результ.Колонки.Добавить("ID");
    Результ.Колонки.Добавить("Name");

    Для каждого Чанк Из РазбитьНаЧанки(IDsМассив, РазмерЧанка) Цикл
        Таб = A1sQ.Unload(ТекстQ, Чанк); // порядок: &Список
        Результ.ЗагрузитьКолонку(Таб.ВыгрузитьКолонку("ID"), "ID");
        Результ.ЗагрузитьКолонку(Таб.ВыгрузитьКолонку("Name"), "Name");
        A1sLog.Info("Day9", "Загружен чанк: " + Чанк.Количество() + " id");
    КонецЦикла;

    Возврат Результ;
КонецФункции
      

Подходит для средних наборов. Для очень больших — смотрите параметры-таблицы.

Паттерн 2 — параметр-таблица (&ВТ) + JOIN

Создаём ТаблицаЗначений с колонкой ID, передаём как параметр &IDs и соединяем её в запросе как виртуальную таблицу.

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


Функция СформироватьВТ_ID(IDsМассив) Экспорт
    ВТ = Новый ТаблицаЗначений;
    ВТ.Колонки.Добавить("ID"); // тип ссылки на справочник Номенклатура
    Для каждого Id Из IDsМассив Цикл
        НовСтр = ВТ.Добавить();
        НовСтр.ID = Id;
    КонецЦикла;
    Возврат ВТ;
КонецФункции
      

Выборка по &IDs через JOIN (эффективно для больших наборов)


Функция НомПоIDsЧерезВТ(IDsМассив) Экспорт
    ВТ = СформироватьВТ_ID(IDsМассив);

    ТекстQ = "
    |ВЫБРАТЬ
    |    Ном.Ссылка       КАК ID,
    |    Ном.Наименование КАК Name
    |ИЗ Справочник.Номенклатура КАК Ном
    |    ВНУТРЕННЕЕ СОЕДИНЕНИЕ &IDs КАК ВТ
    |    ПО Ном.Ссылка = ВТ.ID
    |УПОРЯДОЧИТЬ ПО Name
    ";
    // Параметры позиционно: &IDs
    Возврат A1sQ.Unload(ТекстQ, ВТ);
КонецФункции
      

Этот подход разгружает парсер от длинных «IN (...)» и хорошо работает на больших списках.

Пакетная обработка по периодам

Гоняем запрос «окнами» по дате: день/неделя/месяц. Логируем прогресс.


Процедура ОбработатьРеализацииПоМесяцам(НачПериода, КонПериода) Экспорт
    МесяцНач = НачалоМесяца(НачПериода);
    Пока МесяцНач <= КонПериода Цикл
        МесяцКон = КонецМесяца(МесяцНач);

        ТекстQ = "
        |ВЫБРАТЬ
        |    Док.Ссылка         КАК ID,
        |    Док.Дата           КАК Dt,
        |    Док.СуммаДокумента КАК Amount
        |ИЗ Документ.РеализацияТоваровУслуг КАК Док
        |ГДЕ Док.Дата МЕЖДУ &Начало И &Конец
        ";
        Рез = A1sQ.ExecuteQ(ТекстQ, МесяцНач, МесяцКон);
        Вб  = Рез.Выбрать();

        Сумма = 0; Сч = 0;
        Пока Вб.Следующий() Цикл
            Сумма = Сумма + Вб.Amount;
            Сч = Сч + 1;
        КонецЦикла;

        A1sLog.Info("Day9", Формат(МесяцНач, "ДФ=MM.YYYY") + ": док=" + Сч + ", сумма=" + Сумма);

        МесяцНач = НачалоМесяца(МесяцНач + 31*СекундаВСутках);
    КонецЦикла;
КонецПроцедуры
      

Если выборка за месяц всё равно тяжёлая — добавляйте ПЕРВЫЕ &Лимит и keyset-пагинацию (см. День 7).

Объединение результатов батчей

Иногда нужно одно соответствие ID → Name из многих батчей.


Функция КартаIDкИмени_Батчи(IDs, РазмерЧанка = 500) Экспорт
    ТекстQ = "
    |ВЫБРАТЬ
    |    Ном.Ссылка       КАК ID,
    |    Ном.Наименование КАК Name
    |ИЗ Справочник.Номенклатура КАК Ном
    |ГДЕ Ном.Ссылка В (&Список)
    ";
    Карта = Новый Соответствие;

    Для каждого Ч Из РазбитьНаЧанки(IDs, РазмерЧанка) Цикл
        Таб = A1sQ.Unload(ТекстQ, Ч);
        IDsЧ   = Таб.ВыгрузитьКолонку("ID");
        NamesЧ = Таб.ВыгрузитьКолонку("Name");
        Для Н = 0 По IDsЧ.Количество()-1 Цикл
            Карта.Вставить(IDsЧ[Н], NamesЧ[Н]);
        КонецЦикла;
        A1sLog.Info("Day9", "Карта: +" + Таб.Количество() + " пар");
    КонецЦикла;

    Возврат Карта;
КонецФункции
      

Контроль ошибок и таймаутов


Процедура ОбработатьБатчиСЗащитой(IDs) Экспорт
    Для каждого Ч Из РазбитьНаЧанки(IDs, 500) Цикл
        Попытка
            Таб = A1sQ.Unload("
            |ВЫБРАТЬ Ном.Ссылка КАК ID, Ном.Наименование КАК Name
            |ИЗ Справочник.Номенклатура КАК Ном
            |ГДЕ Ном.Ссылка В (&Список)
            ", Ч);
            A1sLog.Info("Day9", "OK чанк: " + Ч.Количество() + " id");
        Исключение
            A1sLog.Error("Day9", "FAIL чанк: " + ОписаниеОшибки());
            Продолжить; // следующий чанк
        КонецПопытки;
    КонецЦикла;
КонецПроцедуры
      

Практика (15–30 минут)

  1. Соберите батч-выборку по списку ссылок через В (&Список) (чанк 500).
  2. Сделайте вариант с параметром-таблицей &IDs и JOIN — сравните время.
  3. Реализуйте обработку документов по месяцам и залогируйте сумму/кол-во по каждому месяцу.
  4. Соберите «карту» ID → Name из батчей и проверьте уникальность ключей.

Чек-лист

Что дальше

День 10: A1sO — проверки значений (Empty, NotEmpty) и базовые предикаты.