В практике разработчика 1С часто возникает ситуация, когда необходимо обработать данные, которые еще не записаны в базу или были получены из внешних источников. Мы помещаем ТаблицуЗначений в Запрос, выполняем соединения, группировки и сортировки. На первый взгляд кажется, что раз обращения к реальным таблицам БД (справочникам или документам) нет, то и СУБД (SQL Server) в этом процессе не участвует. Но так ли это на самом деле?
Разберем детально механизм работы платформы «1С:Предприятие 8» в клиент-серверном варианте при обработке таблиц значений в языке запросов.
Существует распространенное заблуждение, что если запрос не обращается к данным базы, то его выполняет непосредственно сервер приложений 1С своими внутренними алгоритмами. Однако это верно лишь отчасти и только для файлового варианта работы базы данных.
В клиент-серверном режиме платформа придерживается строгой архитектуры: любой объект типа Запрос транслируется в нативный SQL-код и отправляется на исполнение серверу баз данных (MS SQL, PostgreSQL, Oracle или IBM DB2). Рассмотрим, почему это происходит именно так:
Чтобы понять, что происходит «под капотом», проанализируем пример реального запроса 1С, который выбирает данные из переданного параметра &ВТ (Таблица Значений):
// Запрос в 1С
ВЫБРАТЬ
ВТ.НомерСтроки КАК НомерСтроки,
ВТ.Сумма КАК Сумма
ПОМЕСТИТЬ ВременнаяТаблица
ИЗ
&ВТ КАК ВТ;
ВЫБРАТЬ
ВременнаяТаблица.НомерСтроки,
ВременнаяТаблица.Сумма
ИЗ
ВременнаяТаблица;
Если мы воспользуемся консолью запросов или профайлером SQL, мы увидим, что 1С генерирует следующий T-SQL код:
-- 1. Инициализация структуры временной таблицы
INSERT INTO #tt271 WITH(TABLOCK) (_Q_001_F_000, _Q_001_F_001)
SELECT TOP 0 CAST(NULL AS NUMERIC(10, 0)), CAST(NULL AS NUMERIC(15, 3))
-- 2. Наполнение таблицы данными из нашей ТЗ
INSERT INTO #tt271 (_Q_001_F_000, _Q_001_F_001)
VALUES(1, 123.00), (2, 11.00), (3, -344.02)
-- 3. Итоговая выборка
SELECT T1._Q_001_F_000, T1._Q_001_F_001
FROM #tt271 T1 WITH(NOLOCK)
Здесь #tt271 — это временная таблица на стороне SQL-сервера. Разберем по шагам, что сделал сервер 1С:
ТаблицеЗначений.CAST для жесткой типизации полей в SQL.Важно понимать, что даже если вы не трогаете основные таблицы вашей ИБ, нагрузка на дисковую подсистему всё равно создается. Все временные таблицы (начинающиеся с символа #) создаются в системной базе данных tempdb.
Если ваша ТаблицаЗначений содержит сотни тысяч строк, 1С будет вынуждена сериализовать эти данные, передать их по сети на SQL-сервер, а тот, в свою очередь, запишет их в tempdb. В некоторых случаях это может стать узким местом, особенно если tempdb расположена на медленных дисках или ограничена в росте.
Многие разработчики спорят: стоит ли использовать запрос или лучше обойтись методами объекта ТаблицаЗначений (НайтиСтроки(), Скопировать(), Свернуть()). Выясним преимущества запросов:
НайтиСтроки() нельзя использовать сложные логические операторы ИЛИ, НЕ или вложенные условия. В запросе же доступна вся мощь условий ГДЕ.ИНДЕКСИРОВАТЬ ПО.... В этом случае SQL-сервер создаст индекс для временной таблицы, что на порядки ускорит последующие соединения.Проанализируем ситуацию с типами данных. Если колонка вашей ТаблицыЗначений не имеет четко заданного типа (тип Произвольный или составной тип), 1С создаст в SQL-сервере максимально «широкую» структуру.
Например, для колонки с типом «ЛюбаяСсылка» SQL-сервер создаст несколько полей (идентификатор типа, бинарный код ссылки), что увеличит размер временной таблицы в разы. Поэтому всегда типизируйте колонки ТЗ перед передачей их в запрос — это сэкономит память и ускорит передачу данных по сети.
Рассмотрим кратко файловый вариант. В нем «движком» базы данных выступает сама библиотека платформы. Здесь трансляции в T-SQL не происходит, но логика остается похожей: создаются внутренние структуры в оперативной памяти (или во временных файлах на диске), которые обрабатываются тем же кодом, что и обычные таблицы .1CD. Накладные расходы на сеть здесь отсутствуют, но общая производительность ограничена мощностью одного рабочего процесса.
Запросы к таблицам значений — это мощный инструмент, но его нужно использовать осознанно. Мы выяснили, что основной объем вычислительной работы в клиент-серверном варианте выполняет SQL-сервер.
Основные правила для оптимизации:
ТаблицыЗначений.tempdb и сетевой трафик между сервером 1С и сервером БД.НайтиСтроки() могут оказаться быстрее за счет отсутствия накладных расходов на передачу данных в СУБД.