Как эффективнее проверить наличие строк в табличной части: через запрос или встроенными методами 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки на платформе 1С:Предприятие 8 часто возникает задача поиска данных внутри табличной части (ТЧ) или таблицы значений (ТЗ) на стороне сервера. Например, нам нужно быстро узнать, есть ли в таблице хотя бы одна строка, где поле Признак имеет значение Ложь. На первый взгляд кажется, что запрос — это универсальный и самый мощный инструмент, но так ли это, когда речь идет о данных, которые уже находятся в оперативной памяти сервера приложений? Рассмотрим этот вопрос детально, проанализируем аппаратные затраты и выберем оптимальный подход.

Метод 1: Использование встроенных методов поиска в оперативной памяти

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

Вариант А: Метод Найти()

Если нам нужно просто проверить факт наличия значения, метод Найти() является наиболее эффективным. Рассмотрим его работу: он сканирует таблицу до первого нахождения и сразу прекращает поиск (алгоритм с ранним выходом). Это минимизирует количество итераций.


// Поиск одной строки
СтрокаТаблицы = Объект.Товары.Найти(Ложь, "Признак");
Если СтрокаТаблицы <> Неопределено Тогда
    // Мы нашли хотя бы одну строку
КонецЕсли;

Вариант Б: Метод НайтиСтроки()

Разберем ситуацию, когда нам может понадобиться список всех подходящих строк. Метод НайтиСтроки() принимает структуру фильтра и возвращает массив ссылок на строки табличной части.


ПараметрыОтбора = Новый Структура("Признак", Ложь);
МассивСтрок = Объект.Товары.НайтиСтроки(ПараметрыОтбора);
Если МассивСтрок.Количество() > 0 Тогда
    // Обработка найденных строк
КонецЕсли;

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

Вариант В: Метод Выгрузить() с фильтром

Посмотрим на более тяжелый способ — выгрузку части данных в новую таблицу значений. Это полезно, если результат нужно передать в другую функцию, ожидающую именно ТаблицаЗначений.


Фильтр = Новый Структура("Признак", Ложь);
ТЗРезультат = Объект.Товары.Выгрузить(Фильтр, "Признак, Номенклатура, Количество");

Внимание: этот метод самый ресурсозатратный, так как он физически копирует данные из памяти в память, создавая новый объект.

Метод 2: Использование запроса к таблице-параметру

Теперь выясним, что происходит, когда мы пытаемся написать запрос к табличной части, передавая её как параметр. На первый взгляд код выглядит привычно:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ВременнаяТаблица.НомерСтроки
    |ПОМЕСТИТЬ ВТ_Данные
    |ИЗ
    |   &ТЧ КАК ВременнаяТаблица
    |ГДЕ
    |   ВременнаяТаблица.Признак = ЛОЖЬ
    |;
    |ВЫБРАТЬ ПЕРВЫЕ 1
    |   ВТ_Данные.НомерСтроки
    |ИЗ
    |   ВТ_Данные КАК ВТ_Данные";

Запрос.УстановитьПараметр("ТЧ", Объект.Товары.Выгрузить());
РезультатЗапроса = Запрос.Выполнить();

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

  1. Сериализация: Данные из памяти сервера приложений преобразуются в поток для передачи.
  2. Передача данных: Весь объем ТЧ отправляется по сети на SQL-сервер.
  3. Создание временной таблицы: СУБД (например, MS SQL или PostgreSQL) получает данные и записывает их в свою системную базу (tempdb). Это дисковая операция записи.
  4. Выполнение запроса: SQL-сервер парсит запрос, строит план и выполняет поиск в tempdb.
  5. Возврат результата: Результат снова упаковывается и отправляется по сети обратно на сервер приложений 1С.

Вывод: Для простых проверок использование запроса к ТЧ — это "стрельба из пушки по воробьям". Накладные расходы на сетевой трафик и дисковые операции в СУБД в десятки раз превысят время работы простого цикла в памяти.

Когда запрос к таблице действительно необходим?

Несмотря на вышесказанное, существуют ситуации, когда запрос — единственный верный путь. Рассмотрим их:

Сравнение на аппаратном уровне

Разберем разницу в нагрузке на "железо":

1. При использовании методов ТЗ/ТЧ (Найти, цикл): Нагружается только центральный процессор (CPU) сервера приложений 1С. Используется уже выделенная оперативная память (RAM). Это максимально быстрый путь.

2. При использовании Запроса: Нагружается сетевой стек (между 1С и SQL), CPU сервера базы данных, а главное — дисковая подсистема сервера БД из-за работы с временными таблицами в tempdb. Для мониторинга таких параметров и выявления узких мест на стороне СУБД подойдёт обработка для анализа нагрузки и запросов SQL-сервера.

Практические рекомендации

Выясним итоговый алгоритм выбора метода:

  1. Если нужно просто проверить наличие значения или найти одну/несколько строк для обработки "здесь и сейчас" — используйте Найти() или НайтиСтроки().
  2. Если вы работаете с очень большой таблицей значений (тысячи строк) и часто выполняете в ней поиск — рассмотрите возможность индексации в памяти. Для этого ТЧ нужно выгрузить в ТЗ и вызвать ТаблицаЗначений.Индексы.Добавить("Признак"). Это создаст хеш-таблицу в RAM, и поиск станет мгновенным.
  3. Используйте Запрос только тогда, когда данные из таблицы являются лишь "входным билетом" для получения других данных из базы через соединения (СОЕДИНЕНИЕ) или объединения (ОБЪЕДИНИТЬ).

Для более глубокого погружения в тему рекомендуем изучить Стандарты разработки 1С (раздел "Работа с запросами") и литературу по оптимизации производительности, где детально разбирается работа технологического журнала и событий DBMSSQL, возникающих при передаче таблиц в параметры запроса. Для быстрой расшифровки полученных из журнала запросов в термины метаданных конфигурации можно использовать инструмент для перевода SQL-запросов профайлера в объекты 1С.

← На главную