← вся теориятеория к собесу · Оптимизация запросов 1С

Медленные запросы 1С: запрос в цикле и другие ошибки

разбор писал Даниил, автор Сеньорчика

Зачем это спрашивают

Медленный код в 1С чаще всего медленный из-за нескольких повторяющихся ошибок в запросах. На собесе дают кусок кода и просят найти, что тормозит. Главный кандидат почти всегда запрос в цикле, следом идут звёздочка, РАЗЛИЧНЫЕ поверх размножения и функции над полями.

// Так спрашивают: «Что не так с запросом в цикле?» «Чем плох ВЫБРАТЬ *?» «Почему РАЗЛИЧНЫЕ не лечит размножение строк?» «Какие условия не используют индекс?»

Запрос в цикле

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

Второй вариант отвечает за одно обращение независимо от числа строк. В первом время растёт вместе с документом, и проведение на тысяче строк превращается в минуту.

Каталог ошибок

Остальные ошибки узнаются по тексту запроса ещё до замеров. Частые собраны в таблицу:

Клиент и сервер

Объекта Запрос на клиенте нет. Код, который пытается получить данные отчёта запросом в клиентской процедуре, не скомпилируется, а попытка обойти это множеством мелких серверных вызовов из цикла на клиенте даёт тот же запрос в цикле, только ещё и через сеть клиента. Данные готовят одним серверным вызовом.

Если запрос написан хорошо, а всё равно тормозит, причина ниже: план запроса в СУБД, индексы, статистика. Её ищут в технологическом журнале и в плане запроса, об этом следующие главы.

Как отвечать: «Вот проведение документа на 500 строк, оно идёт 40 секунд. Где искать?»

Сначала посмотрю на запросы в цикле по строкам: цены, остатки, реквизиты через точку. На 500 строк это 500 обращений к базе и больше, и время растёт вместе с размером документа. Их заменяю одним пакетом: табличная часть во временную таблицу и соединение. Потом проверю виртуальные таблицы без параметров и РАЗЛИЧНЫЕ поверх соединений. Чтобы не гадать, сниму замер производительности, он покажет строки кода с наибольшим временем.

Ответ начинает с самой вероятной причины, даёт способ лечения и заканчивается инструментом, который превращает догадку в цифры.

На чём валят

  • −Запрашивают данные в цикле по строкам. N обращений вместо одного. Временная таблица и соединение.
  • −Пишут ВЫБРАТЬ * в рабочих запросах. Тянутся лишние поля и хранилища. Перечисляют поля.
  • −Лечат дубли РАЗЛИЧНЫЕ. Ошибка соединения остаётся, результат сортируется целиком. Сворачивают правую сторону.
  • −Соединяют документ с Остатки() без параметров. Расчёт по всему регистру. Отбор по товарам документа в параметре.

Проверь себя

Пять вопросов из банка по этой подтеме. Всего их 12, остальные разбираются в тренажёре.

  1. #oc_q_antipatterns1 / 5
    Чем плох РАЗЛИЧНЫЕ в запросе, который возвращает дубли после соединения?
    A)РАЗЛИЧНЫЕ не убирает дубли после соединения
    B)РАЗЛИЧНЫЕ работает только для ссылок
    C)РАЗЛИЧНЫЕ запрещён вместе с соединениями
    D)Он прячет ошибку соединения и добавляет работу
    показать ответ и разбор
    +D)Он прячет ошибку соединения и добавляет работу

    // разбор: Если соединение размножает строки, РАЗЛИЧНЫЕ схлопнет их ценой сортировки или хэширования всего результата, а суммы рядом уже могут быть посчитаны неверно. Правильнее понять, почему пара не одна, и свернуть правую сторону до соединения.

  2. #oc_q_antipatterns2 / 5
    Условие ПОДОБНО "%" + &Строка + "%" по наименованию в справочнике на 2 млн строк. В чём проблема?
    A)ПОДОБНО не работает с параметрами
    B)Конкатенация в условии запрещена
    C)Шаблон с % в начале не использует индекс
    D)Регистр символов ломает сравнение
    показать ответ и разбор
    +C)Шаблон с % в начале не использует индекс

    // разбор: Индекс по наименованию помогает только поиску по началу строки. Шаблон, начинающийся с %, заставляет СУБД проверить каждую строку таблицы. Для поиска подстроки по большим справочникам используют полнотекстовый поиск или поиск по началу слова.

  3. #oc_q_antipatterns3 / 5
    Найди проблему:
    Для Каждого Стр Из Товары Цикл
      Запрос.УстановитьПараметр("Т", Стр.Товар);
      Ост = Запрос.Выполнить().Выгрузить();
      Стр.Остаток = Ост.Итог("Количество");
    КонецЦикла;
    A)Итог() не работает на выгруженной таблице
    B)УстановитьПараметр нельзя вызывать повторно
    C)Запрос в цикле по строкам
    D)Выгрузить() внутри цикла запрещён
    показать ответ и разбор
    +C)Запрос в цикле по строкам

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

  4. #oc_q_antipatterns4 / 5
    Запрос соединяет документ с РегистрНакопления.Товары.Остатки() без параметров. Что не так?
    A)Остатки нельзя соединять с документами
    B)Остатки считаются по всем товарам и складам
    C)Соединение с виртуальной таблицей запрещено
    D)Без параметров таблица возвращает пустой результат
    показать ответ и разбор
    +B)Остатки считаются по всем товарам и складам

    // разбор: Виртуальная таблица без условий рассчитает остатки по всему регистру, а соединение потом выкинет почти всё. Отбор по товарам документа передают в параметр: Остатки(, Товар В (ВЫБРАТЬ Товар ИЗ ВТ_Товары)). Это и стандарт, и обычная причина медленного проведения.

  5. #oc_q_antipatterns5 / 5
    Что не так с условием ГДЕ ВЫБОР КОГДА &Все ТОГДА ИСТИНА ИНАЧЕ Т.Склад = &Склад КОНЕЦ?
    A)СУБД не может использовать индекс по складу
    B)Параметр &Все нельзя использовать в ВЫБОР
    C)Результат будет неверным при &Все = Ложь
    D)ВЫБОР в условии ГДЕ запрещён
    показать ответ и разбор
    +A)СУБД не может использовать индекс по складу

    // разбор: Условие, зависящее от параметра через ВЫБОР, СУБД не может свести к поиску по индексу: план строится один на оба случая. Отбор по необязательному параметру лучше собирать текстом запроса (добавлять условие только когда оно нужно) или использовать СКД, где отборы подставляются сами.

дальше

Теорию прочитал. Навык ставится повторением

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