Как ускорить поиск в табличной части документа и правильно настроить индексацию реквизитов

Программист Управленческий учет IT и автоматизация бизнеса
← На главную

В процессе разработки и поддержки крупных информационных систем на платформе 1С:Предприятие часто возникает ситуация, когда объем данных в одном документе (например, в «Установке цен номенклатуры») достигает нескольких тысяч строк. В таких случаях стандартные механизмы поиска начинают работать медленно, вызывая задержки в 2–3 минуты. Разберем подробно, как работает индексация табличных частей, почему включение флажка «Индексировать» в конфигураторе не всегда решает проблему мгновенно, и какие механизмы платформы задействуются в разных сценариях.

Физическая индексация на уровне SQL Server

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

  1. Фоновое выполнение: Современные версии MS SQL Server позволяют выполнять создание индексов в режиме ONLINE. Это означает, что база данных остается доступной, а индекс строится параллельно. Если данных не миллионы строк, 1С пролетает этап реструктуризации крайне быстро.
  2. Состав индекса: Важно понимать, что для табличных частей 1С создает не одиночный индекс по реквизиту, а составной. Обычно это связка [Ссылка + Реквизит] или [Реквизит + Ссылка]. Это необходимо для того, чтобы SQL-сервер мог быстро отфильтровать строки, принадлежащие конкретному документу.
  3. Проверка через SQL: Чтобы убедиться, что индекс создан, мы можем заглянуть в консоль SQL Management Studio. Таблицы табличных частей документов имеют префикс _DocumentChng.... Найдя нужную таблицу, мы увидим список индексов в соответствующей ветке дерева объекта.

Почему индекс в метаданных не ускоряет поиск в форме?

Рассмотрим ситуацию, на которую часто жалуются разработчики: индекс включен, но НайтиСтроки() в открытой форме документа все равно «тормозит». Разберем причину этого явления. Платформа 1С разделяет работу с данными на два уровня:

1. Объектная техника (Данные в памяти): Когда документ открыт в форме, все строки его табличной части уже считаны из базы данных и находятся в оперативной памяти (в коллекции ТабличнаяЧасть или в ТаблицеЗначений, если речь идет о программной обработке). Когда пользователь выполняет поиск в экранной форме или программист использует метод НайтиСтроки(), система не обращается к SQL-серверу. Она перебирает данные прямо в памяти. Индекс, созданный в конфигураторе для SQL, здесь абсолютно бесполезен.

2. Запросная техника: Индекс в метаданных будет эффективно работать только в том случае, если поиск выполняется через объект Запрос. Например:


Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Документ.УстановкаЦенНоменклатуры.Товары ГДЕ Номенклатура = &Номенклатура";
// Здесь индекс SQL будет задействован максимально эффективно

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

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


// Выгружаем ТЧ в таблицу значений для быстрой обработки
тзТовары = Товары.Выгрузить();
// Создаем индекс в памяти. Это работает очень быстро
тзТовары.Индексы.Добавить("Номенклатура");

// Теперь поиск через НайтиСтроки будет мгновенным
ПараметрыОтбора = Новый Структура("Номенклатура", ИскомыйТовар);
НайденныеСтроки = тзТовары.НайтиСтроки(ПараметрыОтбора);

Важный момент: Для обычных форм в документе «Установка цен номенклатуры» часто используется не стандартная табличная часть, а дерево значений или динамически формируемая таблица цен. В этом случае стандартная индексация реквизита в дереве объектов метаданных вообще не имеет смысла для интерфейса.

Роль критериев отбора в индексации

Проанализируем совет использовать КритерииОтбора. Это специальный объект метаданных, который позволяет быстро находить документы по значению определенного реквизита.

Если мы добавим реквизит табличной части в состав критерия отбора (например, «ПоискПоНоменклатуре»), платформа автоматически установит для этого реквизита свойство индексации. Это гарантирует, что в базе данных будет создан индекс, оптимизированный для поиска ссылок на документы. Если ваша задача — быстро найти, в каких документах «Установка цен» встречается конкретная позиция товара, критерии отбора — лучший инструмент.

Разбор групповой обработки: «Обрабатывать табличные части»

Выясним, что означает флаг «Обрабатывать табличные части» в стандартной групповой обработке справочников и документов (часто используемой в обычном интерфейсе). Это важный инструмент для массовых изменений данных:

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

Если поиск в табличной части на 5000–6000 строк занимает 2–3 минуты, скорее всего, проблема не в отсутствии индекса, а в алгоритме обработки событий. Проанализируем возможные «узкие места»:

  1. Обработчик ПриВыводеСтроки: Если в этом обработчике есть обращения к серверу, получение остатков или цен через запросы — это убьет производительность. При поиске (скроллинге) эти события вызываются для каждой строки.
  2. Клиент-серверные вызовы: Проверьте, не вызывается ли серверный метод в цикле при обходе строк табличной части. Каждый такой вызов — это сетевая задержка. Правильно будет собрать все данные в массив, передать его на сервер один раз, получить результат и обработать его на клиенте.
  3. Обновление формы: Иногда поиск (программное изменение текущей строки) вызывает цепочку событий ПриАктивизацииСтроки, которые инициируют тяжелое обновление связанных элементов формы. Попробуйте на время поиска отключать обработчики событий или использовать ЭтаФорма.ОбновлениеОтображения(Ложь).

Таким образом, для решения проблемы медленного поиска мы должны сначала определить, где именно происходит задержка: на уровне SQL при выполнении запроса или на уровне интерфейса в памяти. В зависимости от этого выбирается метод: индексация в метаданных для запросов или использование Индексы.Добавить() для коллекций в оперативной памяти.

← На главную