При анализе производительности систем на базе 1С:Предприятие одним из самых важных инструментов является план выполнения запроса MS SQL Server. Однако использование русской версии среды Management Studio (SSMS) часто вносит путаницу из-за специфического перевода технических терминов. Разберем подробно, что скрывается за названиями «Поиск ключа» и «Поиск кластеризованного индекса», как они влияют на скорость работы программы и что нужно сделать для оптимизации кода.
Рассмотрим ситуацию, когда в плане запроса мы видим оператор «Поиск ключа». В оригинальной английской версии он называется Key Lookup. Это операция, которая происходит в тот момент, когда СУБД уже успешно нашла ссылку на нужную строку, используя некластеризованный индекс, но обнаружила, что в этом индексе отсутствуют некоторые поля, требуемые в блоке ВЫБРАТЬ (SELECT).
Проанализируем механику этого процесса. Когда мы выполняем запрос к базе данных 1С, SQL Server пытается найти оптимальный путь. Если у нас есть индекс по полю, участвующему в условии ГДЕ, сервер переходит к этому индексу. Однако некластеризованный индекс содержит только те поля, которые в него явно включены, и «закладку» (ссылку) на основную таблицу. Если вашему запросу нужно поле, которого нет в индексе, SQL Server вынужден для каждой найденной строки обращаться к основной таблице (кластеризованному индексу), чтобы «дозабрать» недостающие данные.
Почему это плохо? Выясним причину: если запрос возвращает сотни или тысячи строк, операция «Поиск ключа» превращается в так называемое Random I/O (случайное чтение). Вместо того чтобы прочитать данные одним сплошным блоком, сервер начинает «прыгать» по всей таблице. Это крайне медленно и сильно нагружает дисковую подсистему. В контексте 1С это часто случается, когда программист обращается к реквизитам через точку в запросе или выбирает избыточные поля.
Чтобы «вылечить» эту проблему, мы должны использовать покрывающие индексы. В терминах SQL Server это означает добавление недостающих полей в конструкцию INCLUDE индекса. В 1С мы можем добиться этого, добавляя нужные поля в состав дополнительных колонок индекса или пересматривая структуру запроса, чтобы исключить обращение к лишним данным.
Теперь разберем разницу между двумя ключевыми операциями поиска по основной таблице:
Scan — это полное сканирование таблицы. SQL Server читает таблицу от начала до конца, перебирая каждую строку.Рассмотрим подробнее ситуацию, когда Scan может появиться вместо Seek. Иногда это оправдано: у SQL Server есть так называемая «точка перегиба» (Tipping Point). Если сервер оценивает, что вам нужно прочитать более 25-30% данных всей таблицы, он сознательно выберет Scan, так как последовательное чтение всей таблицы в данном случае будет быстрее, чем постоянные переходы по ссылкам индекса.
В обсуждениях специалистов часто упоминается RID Lookup. Проанализируем, чем он отличается от обычного поиска ключа. RID Lookup — это частный случай, который возникает только в таблицах типа Heap (Куча). Это таблицы, у которых вообще нет кластеризованного индекса. В системе 1С:Предприятие такие таблицы встречаются крайне редко, так как почти все объекты (справочники, документы) имеют первичный ключ, который автоматически становится кластеризованным индексом. Однако вы можете столкнуться с RID Lookup при работе с некоторыми временными таблицами, если они не были проиндексированы должным образом.
Даже если мы создали идеальный индекс, мы можем увидеть в плане запроса Clustered Index Scan вместо ожидаемого Seek. Посмотрим на примеры ситуаций, когда запрос становится не-SARGable (то есть не позволяющим использовать аргументы поиска):
ГДЕ ГОД(ДатаДокумента) = 2023, SQL Server не сможет использовать индекс по полю ДатаДокумента и будет вынужден сканировать всю таблицу.LIKE "%Текст" всегда приводит к полному сканированию, так как поиск по индексу возможен только слева направо.В контексте разработки на платформе 1С, появление операторов «Поиск ключа» или «Сканирование» часто связано с архитектурными особенностями. Разберем по шагам, на что обратить внимание:
Во-первых, это избыточный выбор полей. Если в запросе используется ВЫБРАТЬ * или выбирается очень много реквизитов «на всякий случай», вероятность получения Key Lookup возрастает в геометрической прогрессии. Старайтесь выбирать только те поля, которые действительно нужны для логики алгоритма.
Во-вторых, обратите внимание на использование механизма «Выбрать разрешенные». При проверке прав доступа на уровне записей (RLS) SQL Server вынужден обращаться к дополнительным таблицам прав. Если индексы по полям, участвующим в RLS, не оптимальны, вы увидите массовое сканирование таблиц и падение производительности всей системы.
В-третьих, проанализируем ситуацию с Параллелизмом. Если в плане запроса рядом с иконкой сканирования вы видите две желтые стрелочки, это означает, что SQL Server задействовал несколько ядер процессора для выполнения задачи. Часто это признак того, что системе не хватает подходящего индекса, и она пытается компенсировать неэффективность алгоритма грубой вычислительной мощностью.
Для закрепления материала, вспомним основные методы оптимизации. Если мы обнаружили Key Lookup, нам нужно:
ValueStorage, которые нельзя включать в индексы.Помните, что каждый лишний «Поиск ключа» — это дополнительная нагрузка на сервер, которая при масштабировании системы может стать критической точкой отказа.