Индексы и план запроса в 1С
Индекс ускоряет поиск, если запрос может им воспользоваться. В 1С индексы задают флагами метаданных, а решает, использовать ли их, СУБД (система управления базами данных) по статистике. Ниже планы PostgreSQL 16 на таблице в 200 000 строк: какой отбор идёт по индексу, а какой нет.
// Так спрашивают: «Что делает флаг Индексировать?» «Зачем «Индексировать с доп. упорядочиванием»?» «Сработает ли составной индекс при отборе по второму полю?» «Почему индекс по булеву полю не помогает?»
Индексы из метаданных
Флаг «Индексировать» у реквизита создаёт индекс СУБД по этому полю, и платформа добавляет в него ссылку. Уникальности индекс не даёт: два элемента с одинаковым артикулом запишутся. Вариант «Индексировать с доп. упорядочиванием» добавляет в индекс поле сортировки, и динамический список, который отбирает по реквизиту и сортирует по наименованию, читает порции прямо по индексу.
Индексы создают метаданными, а не руками в СУБД: при реструктуризации платформа пересоздаёт таблицы, и ручной индекс пропадёт. Измерения регистров индексируются платформой сами, порядок измерений задаёт порядок полей индекса.
Составной индекс
Составной индекс работает по первым полям. Индекс по товару и складу помогает отбору по товару, а отбор только по складу пойдёт мимо. Таблица на 200 000 строк, индекс по (товар, склад):
По товару СУБД пошла по индексу (Index Scan): нашла ключ и прочитала одну строку. По складу индекс начинается не с того поля, и СУБД читает таблицу целиком (Seq Scan), проверяя условие на каждой строке. В терминах MS SQL это Seek и Scan.
Для 1С отсюда правило порядка измерений регистра: первыми ставят те, по которым отбирают чаще всего. Регистр с измерениями «склад, товар» плохо отвечает на вопрос «где лежит этот товар».
EXPLAIN (COSTS OFF)
SELECT price FROM prices WHERE item = 777;
EXPLAIN (COSTS OFF)
SELECT price FROM prices WHERE store = 7;Избирательность и статистика
Индекс полезен, когда условие отбирает малую долю строк. Флаг акции стоит у 1% товаров, по нему есть индекс. Отбор «по акции» и «не по акции»:
Для редкого значения индекс сработал, для частого СУБД читает таблицу целиком: 99% строк всё равно придётся прочитать, и прыжки по индексу только добавят работы. Индекс по полю, где почти все значения одинаковы, ускоряет только поиск редкого значения, а писать в таблицу становится дороже: каждая запись обновляет и индекс.
Решение «индекс или полное чтение» СУБД принимает по статистике распределения значений. После загрузки миллиона документов статистика устаревает, и старые планы деградируют. Её обновляют регламентом обслуживания, иначе хороший индекс перестаёт выбираться.
EXPLAIN (COSTS OFF)
SELECT price FROM prices WHERE promo;
EXPLAIN (COSTS OFF)
SELECT price FROM prices WHERE NOT promo;Как отвечать: «Добавили флаг Индексировать на реквизит, а запрос не ускорился. Почему?»
Причин несколько. Условие может не пользоваться индексом: функция над полем, ПОДОБНО с процентом в начале, отбор не по первому полю составного индекса. Поле может быть малоизбирательным, и СУБД разумно выбирает полное чтение. Статистика может быть старой, тогда план не учитывает новый индекс. Проверяю план запроса в СУБД и смотрю, есть ли там поиск по индексу или полное чтение таблицы.
Ответ перебирает причины от кода к СУБД и заканчивается проверкой по плану. Это показывает, что кандидат не верит флагу на слово.
На чём валят
- −Ждут уникальности от флага Индексировать. Индекс не уникальный. Уникальность проверяют кодом или запросом.
- −Индексируют булево поле, где 99% значений одинаковы. По частому значению индекс не помогает, а запись дорожает.
- −Отбирают по второму полю составного индекса. Индекс читается целиком или не используется. Порядок полей под частые отборы.
- −Не обновляют статистику после массовой загрузки. Планы деградируют. Статистику обновляют регламентом.
Проверь себя
Пять вопросов из банка по этой подтеме. Всего их 12, остальные разбираются в тренажёре.
- Есть ли смысл индексировать булев реквизит «ЭтоАрхивный», если 99% записей — Ложь?A)Да: индекс ускорит отбор по ЛожьB)Мало толку: поле малоизбирательноC)Да, если это первый реквизит справочникаD)Нет: булевы реквизиты индексировать нельзя
показать ответ и разбор
+B)Мало толку: поле малоизбирательно// разбор: Индекс выгоден, когда отбор выбирает малую долю строк. По значению Ложь (99% строк) СУБД всё равно прочитает почти всю таблицу. Индекс пригодится только для редкой Истины, и то вместе с другими полями. Платформа индексировать булево поле позволяет.
- Зачем «Индексировать с доп. упорядочиванием»?A)Индекс включит поле сортировкиB)Чтобы реквизит сортировался по убываниюC)Чтобы индекс попал в полнотекстовый поискD)Чтобы индекс по реквизиту стал уникальным
показать ответ и разбор
+A)Индекс включит поле сортировки// разбор: Динамический список отбирает по реквизиту и сортирует по наименованию или коду. Обычный индекс содержит реквизит и ссылку, и сортировку приходится делать отдельно. Доп. упорядочивание добавляет в индекс основное поле упорядочивания (код, наименование, дату), и порции списка читаются по индексу.
- Индекс по (Товар, Склад). Какое условие использует его лучше всего?A)
Товар = &Т И Склад = &СB)Склад = &С ИЛИ Товар = &ТC)ПОДСТРОКА(Товар.Код, 1, 3) = "А-1"D)Склад = &Споказать ответ и разбор
+A)`Товар = &Т И Склад = &С`// разбор: Составной индекс упорядочен по первому полю, затем по второму. Условие на оба поля или на первое ищет по индексу. Только по второму полю — индекс читается целиком. ИЛИ по разным полям и функции над полем мешают поиску.
- Какие индексы платформа создаёт у справочника без индексируемых реквизитов?A)Только по ссылкеB)Ни одного: индексы создаёт администратор СУБДC)По каждому реквизитуD)По ссылке, коду и наименованию
показать ответ и разбор
+D)По ссылке, коду и наименованию// разбор: Платформа сама создаёт индексы по полям, которые нужны ей для типовых операций: по ссылке (кластерный), по коду и по наименованию, по родителю и владельцу при иерархии и подчинении. Индексы по прикладным реквизитам — только по свойству Индексировать.
- Администратор вручную добавил индекс в MS SQL на таблицу регистра. Что с ним будет?A)Он станет частью конфигурации после обновленияB)Он ускорит все запросы базы автоматическиC)Пропадёт при реструктуризацииD)Платформа запретит его создать
показать ответ и разбор
+C)Пропадёт при реструктуризации// разбор: Платформа управляет структурой своих таблиц и при реструктуризации пересоздаёт их по метаданным. Ручные индексы при этом теряются, а их наличие не видно в конфигурации. Индексы задают свойствами метаданных; ручной индекс — временная мера с регламентом восстановления.
дальше
Теорию прочитал. Навык ставится повторением
В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, бесплатная часть практики — одна сессия дня в сутки.