В процессе разработки на платформе 1С:Предприятие 8 часто возникает задача поиска данных внутри табличной части (ТЧ) или таблицы значений (ТЗ) на стороне сервера. Например, нам нужно быстро узнать, есть ли в таблице хотя бы одна строка, где поле Признак имеет значение Ложь. На первый взгляд кажется, что запрос — это универсальный и самый мощный инструмент, но так ли это, когда речь идет о данных, которые уже находятся в оперативной памяти сервера приложений? Рассмотрим этот вопрос детально, проанализируем аппаратные затраты и выберем оптимальный подход.
Проанализируем ситуацию: когда объект (например, документ или справочник) открыт или загружен на сервере, его табличная часть уже находится в оперативной памяти сервера приложений 1С. Платформа предоставляет нам несколько высокоуровневых методов для работы с этими данными без обращения к СУБД.
Вариант А: Метод Найти()
Если нам нужно просто проверить факт наличия значения, метод Найти() является наиболее эффективным. Рассмотрим его работу: он сканирует таблицу до первого нахождения и сразу прекращает поиск (алгоритм с ранним выходом). Это минимизирует количество итераций.
// Поиск одной строки
СтрокаТаблицы = Объект.Товары.Найти(Ложь, "Признак");
Если СтрокаТаблицы <> Неопределено Тогда
// Мы нашли хотя бы одну строку
КонецЕсли;
Вариант Б: Метод НайтиСтроки()
Разберем ситуацию, когда нам может понадобиться список всех подходящих строк. Метод НайтиСтроки() принимает структуру фильтра и возвращает массив ссылок на строки табличной части.
ПараметрыОтбора = Новый Структура("Признак", Ложь);
МассивСтрок = Объект.Товары.НайтиСтроки(ПараметрыОтбора);
Если МассивСтрок.Количество() > 0 Тогда
// Обработка найденных строк
КонецЕсли;
Важно помнить: этот метод всегда сканирует таблицу полностью и создает в памяти массив, что требует дополнительных ресурсов, если строк очень много.
Вариант В: Метод Выгрузить() с фильтром
Посмотрим на более тяжелый способ — выгрузку части данных в новую таблицу значений. Это полезно, если результат нужно передать в другую функцию, ожидающую именно ТаблицаЗначений.
Фильтр = Новый Структура("Признак", Ложь);
ТЗРезультат = Объект.Товары.Выгрузить(Фильтр, "Признак, Номенклатура, Количество");
Внимание: этот метод самый ресурсозатратный, так как он физически копирует данные из памяти в память, создавая новый объект.
Теперь выясним, что происходит, когда мы пытаемся написать запрос к табличной части, передавая её как параметр. На первый взгляд код выглядит привычно:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВременнаяТаблица.НомерСтроки
|ПОМЕСТИТЬ ВТ_Данные
|ИЗ
| &ТЧ КАК ВременнаяТаблица
|ГДЕ
| ВременнаяТаблица.Признак = ЛОЖЬ
|;
|ВЫБРАТЬ ПЕРВЫЕ 1
| ВТ_Данные.НомерСтроки
|ИЗ
| ВТ_Данные КАК ВТ_Данные";
Запрос.УстановитьПараметр("ТЧ", Объект.Товары.Выгрузить());
РезультатЗапроса = Запрос.Выполнить();
Проанализируем техническую сторону этого процесса. Несмотря на то, что ТЧ уже в памяти 1С, для выполнения запроса платформа должна выполнить следующие действия:
tempdb). Это дисковая операция записи.tempdb.Вывод: Для простых проверок использование запроса к ТЧ — это "стрельба из пушки по воробьям". Накладные расходы на сетевой трафик и дисковые операции в СУБД в десятки раз превысят время работы простого цикла в памяти.
Несмотря на вышесказанное, существуют ситуации, когда запрос — единственный верный путь. Рассмотрим их:
N+1 запрос.Разберем разницу в нагрузке на "железо":
1. При использовании методов ТЗ/ТЧ (Найти, цикл): Нагружается только центральный процессор (CPU) сервера приложений 1С. Используется уже выделенная оперативная память (RAM). Это максимально быстрый путь.
2. При использовании Запроса: Нагружается сетевой стек (между 1С и SQL), CPU сервера базы данных, а главное — дисковая подсистема сервера БД из-за работы с временными таблицами в tempdb. Для мониторинга таких параметров и выявления узких мест на стороне СУБД подойдёт обработка для анализа нагрузки и запросов SQL-сервера.
Выясним итоговый алгоритм выбора метода:
Найти() или НайтиСтроки().ТаблицаЗначений.Индексы.Добавить("Признак"). Это создаст хеш-таблицу в RAM, и поиск станет мгновенным.СОЕДИНЕНИЕ) или объединения (ОБЪЕДИНИТЬ).Для более глубокого погружения в тему рекомендуем изучить Стандарты разработки 1С (раздел "Работа с запросами") и литературу по оптимизации производительности, где детально разбирается работа технологического журнала и событий DBMSSQL, возникающих при передаче таблиц в параметры запроса. Для быстрой расшифровки полученных из журнала запросов в термины метаданных конфигурации можно использовать инструмент для перевода SQL-запросов профайлера в объекты 1С.