Разработка и Конфигурация · 9 мин
Как проиндексировать таблицу значений в 1С
Как проиндексировать таблицу значений в 1С: метод ДобавитьИндекс, свойство Индексы, поиск по индексу, типичные ошибки и примеры кода на встроенном языке.
Таблица значений в 1С — один из самых востребованных объектов встроенного языка: в неё загружают результаты запросов, данные из файлов, промежуточные расчёты. Пока строк немного, поиск работает быстро, но при тысячах записей методы Найти() и НайтиСтроки() без индекса начинают заметно тормозить обработку.
Индексация решает эту проблему: платформа строит внутреннюю структуру по указанным колонкам, и поиск перестаёт быть полным перебором строк. Важно понимать, что индекс таблицы значений — это не индекс базы данных, а механизм ускорения работы с коллекцией в памяти на время её жизни.
Ниже разобраны способы добавления индексов, синтаксис на встроенном языке, ситуации, когда индекс реально помогает, и ошибки, которые сводят выигрыш к нулю.
Что такое индекс таблицы значений и когда он нужен
Индекс таблицы значений — это служебная структура, которую платформа строит по одной или нескольким колонкам. Без индекса метод Найти() перебирает строки последовательно: при 100 000 строк и поиске в цикле это даёт квадратичный рост времени работы. С индексом поиск выполняется почти мгновенно независимо от размера таблицы.
Индекс оправдан, когда таблица большая и по ней многократно ищут значения. Классические сценарии: сопоставление двух таблиц в цикле, поиск строк по номенклатуре или контрагенту, проверка дублей перед загрузкой. Если таблица содержит пару десятков строк и обходится один раз — индекс не нужен, его построение займёт больше времени, чем сэкономит.
Как добавить индекс: синтаксис и примеры
Индекс добавляется методом Добавить() коллекции Индексы. В параметре передаётся строка с именами колонок через запятую:
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Номенклатура");
ТЗ.Колонки.Добавить("Количество");
// ... заполнение таблицы ...
ТЗ.Индексы.Добавить("Номенклатура");
// теперь поиск быстрый
Строка = ТЗ.Найти(ИскомаяНоменклатура, "Номенклатура");
Для составного поиска создают индекс по нескольким колонкам. Порядок колонок в индексе должен совпадать с порядком в условии поиска — иначе индекс может не использоваться:
ТЗ.Индексы.Добавить("Склад,Номенклатура");
ПараметрыОтбора = Новый Структура("Склад,Номенклатура", Склад, Товар);
Строки = ТЗ.НайтиСтроки(ПараметрыОтбора);
Проверить, какие индексы уже существуют, можно перебором коллекции:
Для Каждого Индекс Из ТЗ.Индексы Цикл
Сообщить(Индекс.Имя); // список колонок индекса
КонецЦикла;
- 1Создайте таблицу значений и заполните её данными
- 2Определите колонки, по которым выполняется поиск в цикле
- 3Добавьте индекс: ТЗ.Индексы.Добавить("ИмяКолонки")
- 4Убедитесь, что Найти/НайтиСтроки используют именно эти колонки
- 5Замерьте время выполнения до и после — сравните результат
Индексация и методы поиска: как это работает вместе
Индекс ускоряет только те операции, где ищется точное совпадение по индексированным колонкам: Найти(), НайтиСтроки(). Если в структуру отбора передать колонки, которых нет в индексе, платформа выполнит полный перебор — молча, без ошибок, просто медленно.
Важный нюанс: индекс не помогает при поиске по части значения или сравнению «больше/меньше». Для таких задач либо пересматривают логику (например, выносят фильтрацию в запрос), либо используют перебор с условием — индекс здесь бесполезен.
Метод НайтиСтроки() возвращает массив всех подходящих строк, Найти() — только первую. Если по логике нужна одна строка, используйте Найти(): он останавливается на первом совпадении и работает быстрее.
Альтернатива: соответствие вместо индексированной таблицы
Во многих задачах сопоставления «ключ → данные» вместо таблицы значений с индексом выгоднее использовать Соответствие. Доступ по ключу в соответствии мгновенный по своей природе, код получается проще, а индекс строить не нужно:
Соотв = Новый Соответствие;
Для Каждого Строка Из ТЗ Цикл
Соотв.Вставить(Строка.Номенклатура, Строка.Количество);
КонецЦикла;
Количество = Соотв[ИскомаяНоменклатура]; // Неопределено, если нет
Соответствие подходит, когда ключ один и уникален. Если нужен поиск по нескольким колонкам, неуникальные ключи или последующая сортировка и итоги — остаётесь на таблице значений с индексом.
Сравнение вариантов
Универсально: поиск по нескольким колонкам, неуникальные ключи, сортировка, итоги. Требует явного добавления индекса.
Самый быстрый доступ по одному уникальному ключу. Не поддерживает составные ключи, сортировку и группировку.
Если данные ещё не выгружены из БД — фильтрацию и соединение лучше делать запросом, а не таблицей в памяти.
Типичные ошибки при индексации
Первая ошибка — добавлять индекс до заполнения таблицы и надеяться, что он «сам всё ускорит». Индекс перестраивается при изменении данных, поэтому массовая загрузка строк при включённом индексе может работать медленнее, чем без него. Правильный порядок: сначала заполнить таблицу, потом добавить индекс, затем выполнять поиск.
Вторая ошибка — несовпадение колонок индекса и колонок отбора. Индекс по «Склад,Номенклатура» не поможет поиску только по «Номенклатура»: для этого нужен отдельный индекс или другой порядок колонок. Третья частая проблема — поиск по значениям разных типов: если в колонке строка, а ищут числом, совпадения не будет даже с индексом.
Как проверить, что индекс реально работает
Самый надёжный способ — замер времени. Оберните фрагмент поиска в замер через ТекущаяУниверсальнаяДатаВМиллисекундах() до и после добавления индекса. На таблице в десятки тысяч строк с поиском в цикле разница обычно видна невооружённым глазом: секунды против минут.
Дополнительно проверьте, что структура отбора в НайтиСтроки() содержит ровно те колонки, что входят в индекс, и в том же порядке. Если после индексации ускорения нет — почти всегда причина в несовпадении колонок или в том, что узкое место вообще не поиск, а, например, обращения к базе внутри цикла.
Как проверить результат
Заметно сократилось после добавления индекса
Не изменилось — колонки отбора не совпадают с индексом
Содержит индекс с нужными колонками
Пустая — Добавить() не вызван или вызван для другой таблицы
Возвращает строку с искомым значением
Неопределено при заведомо существующем значении — проверьте типы данных
Ограничения и границы применения
Индексы таблицы значений не заменяют индексы базы данных. Если данные можно отфильтровать или соединить запросом — делайте это запросом: СУБД справится эффективнее, чем обработка в памяти. Выгружать в таблицу значений миллионы строк «чтобы потом поискать» — антипаттерн, который упирается в память сервера.
Также помните, что каждый индекс потребляет память и замедляет модификацию таблицы. Не добавляйте индексы «про запас» — только под конкретные операции поиска, которые действительно выполняются многократно.
Что важно запомнить
Индекс добавляется через ТЗ.Индексы.Добавить() после заполнения таблицы, ускоряет Найти и НайтиСтроки по точному совпадению колонок. Для простого сопоставления по уникальному ключу рассмотрите Соответствие, а фильтрацию больших данных оставляйте запросу.
Частые вопросы
Можно ли проиндексировать таблицу значений по колонке с разными типами данных?
Технически колонка может содержать составной тип, и индекс будет построен. Но поиск сработает только при точном совпадении и значения, и типа: строка "001" и число 1 — разные ключи. Лучше привести значения к одному типу при заполнении таблицы.
Сохраняется ли индекс при копировании таблицы методом Скопировать()?
Копия таблицы — новый объект, и индексы по ней нужно добавлять заново. То же относится к таблицам, полученным через Выгрузить() из результата запроса или восстановленным из хранилища значений.
Ускорит ли индекс метод Свернуть() или Сортировать()?
Нет. Индексы таблицы значений используются только для поиска строк по точному совпадению. Свертка и сортировка работают со своими внутренними механизмами и от индексов не зависят.
Сколько индексов можно добавить к одной таблице значений?
Жёсткого ограничения платформа не накладывает, но каждый индекс занимает память и замедляет добавление и удаление строк. Практичный подход — один-два индекса под реально выполняемые операции поиска.
Что быстрее: НайтиСтроки по индексу или запрос к временной таблице?
Если данные уже в памяти и поисков много — индексированная таблица значений обычно быстрее, так как нет обращения к СУБД. Если данные ещё в базе или их объём велик — выгоднее запрос с помещением во временную таблицу и индексацией средствами СУБД.
Как удалить индекс таблицы значений?
Методом ТЗ.Индексы.Удалить(Индекс), передав элемент коллекции индексов, либо очистить всю коллекцию методом Очистить(). Удаление имеет смысл перед массовой модификацией таблицы, чтобы не тратить время на перестройку индекса.