В практике разработки на платформе 1С:Предприятие часто возникает вопрос: насколько критично соблюдать строгий порядок измерений при установке параметров виртуальных таблиц? Существует мнение, что если пропустить первое измерение регистра и установить отбор по второму, индекс перестанет работать. В этой статье мы подробно разберем, почему это не совсем так, как именно СУБД обрабатывает такие запросы и какие механизмы позволяют системе сохранять приемлемую производительность даже при «неправильных» отборах.
Рассмотрим классическую ситуацию: у нас есть регистр накопления ТоварыНаСкладах с измерениями Номенклатура (первое) и Склад (второе). Логика подсказывает, что оптимальный индекс будет выглядеть как Период + Номенклатура + Склад. Проанализируем типичный запрос, в котором мы намеренно игнорируем Номенклатуру:
ВЫБРАТЬ
ТоварыНаСкладахОстатки.Номенклатура,
ТоварыНаСкладахОстатки.Склад,
ТоварыНаСкладахОстатки.КоличествоОстаток
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &СкладОтбора) КАК ТоварыНаСкладахОстатки
Многие разработчики полагают, что в данном случае индекс будет полностью игнорирован. Однако это заблуждение. Выясним причину: виртуальная таблица остатков физически обращается к таблице итогов (обычно это таблица с префиксом _AccumRegTotals). В этой таблице платформа 1С автоматически создает индекс, первым полем которого всегда является Period (Период), а далее следуют измерения в порядке их следования в метаданных.
Для понимания того, что происходит «под капотом» СУБД (MS SQL Server или PostgreSQL), нам необходимо различать два основных метода работы с индексом:
ГДЕ (или в параметрах виртуальной таблицы) указаны все ведущие поля индекса подряд без пропусков.Seek по складу. Однако она все еще может использовать индекс. Поскольку индекс содержит поле Period, СУБД сначала ограничивает диапазон данных по периоду (например, начало текущего месяца), а затем начинает сканировать все записи внутри этого периода в поисках нужного склада.Проанализируем ситуацию: почему Index Scan в данном случае все равно лучше, чем полный поиск по всей таблице (Table Scan)? Ответ кроется в понятии покрывающего индекса. Индекс таблицы итогов содержит в себе не только измерения, но и ресурсы (значения остатков). Это означает, что СУБД не нужно обращаться к основной таблице данных — все необходимые значения уже есть в самом индексе. Чтение только индекса всегда быстрее чтения всей таблицы.
Рассмотрим подробнее, как современные СУБД (например, PostgreSQL 13+ или Oracle) оптимизируют такие запросы. Существует технология Index Skip Scan (пропускающее сканирование индекса). Работает она следующим образом: если у пропущенного первого поля (в нашем примере — Номенклатура) относительно немного уникальных значений, оптимизатор может решить не сканировать весь период подряд. Вместо этого он как бы «перепрыгивает» от одной номенклатуры к другой, выполняя внутри каждой маленькие поиски Seek по складу.
В MS SQL Server аналогичный механизм может имитироваться оптимизатором, но его эффективность сильно зависит от статистики. Выясним роль статистики: если оптимизатор увидит, что выбранный Склад содержится в 90% записей, он может вообще отказаться от использования индекса и выбрать Table Scan, так как это потребует меньше операций ввода-вывода.
Важно помнить о специфике работы 1С в облачных режимах или при использовании разделения данных. Рассмотрим структуру индекса в этом случае. Если включен Разделитель области данных, он становится первым полем в индексе, даже перед периодом. Платформа 1С автоматически добавляет фильтр по разделителю в каждый запрос. Это позволяет индексу «работать» с самого первого поля, что значительно упрощает задачу планировщику СУБД.
Посмотрим на пример того, как порядок измерений влияет на текущие остатки. Если мы получаем остатки на текущий момент (без указания параметра &Период), платформа обращается к таблице текущих итогов. Там поля Period нет (оно фиксировано для всех записей), и индекс начинается сразу с измерений. В этом случае пропуск первого измерения (Номенклатура) нанесет гораздо более серьезный удар по производительности, так как СУБД сложнее ограничить объем данных для сканирования.
Подведем итог и сформулируем правила для эффективной работы с виртуальными таблицами остатков:
Организация или Склад, если их мало, а номенклатуры много).Index Scan там, где вы ожидали Index Seek.Таким образом, утверждение о том, что индекс «прекрасно работает» даже при пропуске измерения, верно лишь отчасти. Индекс действительно используется СУБД как более компактная копия данных, но эффективность такого использования (Scan вместо Seek) значительно ниже. Понимание этого различия позволяет осознанно подходить к проектированию метаданных и написанию сложных запросов в 1С.