В практике разработки на платформе 1С:Предприятие 8 часто возникает вопрос оптимизации запросов, связанных с использованием временных таблиц (ВТ). Типичная ситуация: мы помещаем во временную таблицу список уникальных ссылок (например, СправочникСсылка.Номенклатура или ДокументСсылка.ЗаказПокупателя) для дальнейшего соединения с другими таблицами. Возникает дилемма: стоит ли тратить время на индексирование этой таблицы, если все записи в ней и так уникальны, а поле всего одно? Давайте подробно разберем этот вопрос с точки зрения теории баз данных и механизмов платформы 1С.
Проанализируем базовый механизм работы СУБД при поиске данных. Если временная таблица не проиндексирована, поиск нужной записи выполняется методом Full Table Scan (полное сканирование). Это означает, что системе приходится просматривать каждую строку таблицы одну за другой. Время такого обхода растет линейно (O(N)): чем больше записей, тем дольше поиск.
Когда мы создаем индекс, СУБД строит структуру, чаще всего это B-дерево (B-Tree). В такой структуре данные упорядочены. Рассмотрим, как это работает: поиск в сбалансированном дереве выполняется за логарифмическое время (O(log N)). Если в вашей таблице 1000 записей, при линейном обходе может потребоваться до 1000 операций сравнения, в то время как поиск по индексу потребует всего около 10 операций. Тот факт, что записи уникальны, никак не отменяет эффективность дерева — наоборот, высокая селективность (уникальность каждой записи) делает индекс максимально эффективным инструментом для точечного поиска.
Рассмотрим ситуацию, когда наша временная таблица состоит всего из одного поля, и именно по нему мы создаем индекс. В терминах СУБД (таких как MS SQL Server или PostgreSQL) такой индекс становится покрывающим. Это означает, что сам индекс уже содержит все данные, которые есть в таблице.
Выясним, почему это важно для производительности. Когда оптимизатор СУБД видит, что все необходимые данные для соединения или выборки присутствуют непосредственно в структуре индекса, он может полностью исключить этап обращения к самой временной таблице (Data Pages). Система работает только с компактной структурой индекса в оперативной памяти, что значительно сокращает количество операций ввода-вывода (I/O).
Наличие индекса во временной таблице критически влияет на то, какой алгоритм выберет СУБД для соединения этой таблицы с другими (например, с виртуальными таблицами остатков или оборотов). Проанализируем основные варианты:
tempdb на диск. Наличие индекса позволяет избежать этого риска и использовать более предсказуемые алгоритмы.Мало кто знает, что использование инструкции ИНДЕКСИРОВАТЬ ПО в языке запросов 1С выполняет не только построение индекса. Платформа при создании индекса инициирует обновление статистики для этой временной таблицы на уровне СУБД.
Статистика — это информация о распределении данных и количестве строк в таблице. Поскольку временные таблицы создаются динамически, оптимизатор СУБД часто «не знает», сколько в них строк — 1 или 100 000. Без актуальной статистики оптимизатор может ошибиться и выбрать неверную «ведущую» таблицу в сложном запросе, что приведет к замедлению выполнения в десятки раз. Создание индекса гарантирует, что СУБД получит точные данные о размере ВТ.
Несмотря на пользу индексов, их создание требует ресурсов (процессорное время и запись в tempdb). Выясним, где проходит «золотая середина»:
Table Scan и крайне медленный запрос слишком велик.Посмотрим на примере, как правильно описывать индексирование в пакете запросов. Допустим, мы отбираем номенклатуру, по которой были возвраты, и хотим использовать её для дальнейшего анализа:
// Первый запрос пакета: формирование ВТ с индексацией
ВЫБРАТЬ РАЗЛИЧНЫЕ
Продажи.Номенклатура КАК Номенклатура
ПОМЕСТИТЬ ВТ_НоменклатураДляАнализа
ИЗ
РегистрНакопления.Продажи КАК Продажи
ГДЕ
Продажи.ТипОперации = ЗНАЧЕНИЕ(Перечисление.ТипыОпераций.Возврат)
ИНДЕКСИРОВАТЬ ПО
Номенклатура
;
// Второй запрос пакета: соединение с ВТ
ВЫБРАТЬ
ВТ.Номенклатура,
Цены.Цена
ИЗ
ВТ_НоменклатураДляАнализа КАК ВТ
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК Цены
ПО ВТ.Номенклатура = Цены.Номенклатура
Важно помнить, что тип СправочникСсылка в базе данных хранится как уникальный идентификатор (GUID). Это 16-байтовое бинарное значение. СУБД прекрасно справляется с индексированием таких полей. Даже если записи абсолютно уникальны, индекс позволяет СУБД обращаться к ним точечно. Если ваша база данных «толстая» (большой объем данных), а запрос охватывает длительный период (например, год), отсутствие индекса на ВТ может заставить систему сканировать миллионы записей в реальных таблицах вместо эффективного использования индексов этих таблиц через Nested Loops.
Рассмотрев все технические аспекты, мы можем сделать однозначный вывод: индексировать временную таблицу с одним полем ссылочного типа необходимо, если количество записей в ней превышает несколько десятков. Это не только ускоряет поиск за счет логарифмической структуры дерева, но и предоставляет оптимизатору СУБД актуальную статистику и возможность использовать наиболее эффективные алгоритмы соединения таблиц. Создание индекса — это «страховка», которая гарантирует стабильную производительность вашего отчета или обработки по мере роста объема данных в информационной базе.