В практике разработчика 1С часто возникает ситуация, когда два практически идентичных запроса показывают колоссальную разницу в производительности. В нашем случае один запрос выполняется за 0,022 секунды, а второй — за 3,425 секунды. При этом структура запросов совпадает, а разница заключается лишь в поле, по которому строится условие ГДЕ. Проанализируем эту ситуацию, выясним скрытые причины такого поведения системы и найдем способы оптимизации.
Рассмотрим два запроса к документу ЗаказКлиента. Оба запроса ограничивают выборку по периоду ДатаОтгрузки и статусу Проведен.
Запрос №1 (быстрый):
ВЫБРАТЬ
ЗаказКлиента.Ссылка КАК Ссылка,
ЗаказКлиента.СуммаДокумента КАК СуммаДокумента,
ЗаказКлиента.Склад КАК Склад,
ЗаказКлиента.ДатаОтгрузки КАК ДатаОтгрузки
ИЗ
Документ.ЗаказКлиента КАК ЗаказКлиента
ГДЕ
ЗаказКлиента.ДатаОтгрузки >= ДАТАВРЕМЯ(2023, 1, 1)
И ЗаказКлиента.ДатаОтгрузки <= ДАТАВРЕМЯ(2023, 12, 31)
И ЗаказКлиента.Партнер = &Партнер
И ЗаказКлиента.Проведен = ИСТИНА
Запрос №2 (медленный):
ВЫБРАТЬ
ЗаказКлиента.Ссылка КАК Ссылка,
ЗаказКлиента.СуммаДокумента КАК СуммаДокумента,
ЗаказКлиента.Склад КАК Склад,
ЗаказКлиента.ДатаОтгрузки КАК ДатаОтгрузки
ИЗ
Документ.ЗаказКлиента КАК ЗаказКлиента
ГДЕ
ЗаказКлиента.ДатаОтгрузки >= ДАТАВРЕМЯ(2023, 1, 1)
И ЗаказКлиента.ДатаОтгрузки <= ДАТАВРЕМЯ(2023, 12, 31)
И ЗаказКлиента.Грузополучатель = &Грузополучатель
И ЗаказКлиента.Проведен = ИСТИНА
Несмотря на схожесть, второй запрос работает в 150 раз медленнее. Разберем по шагам, какие факторы влияют на такую разницу.
Первым делом проанализируем метаданные. Часто разработчики смотрят только на свойство Индексировать у конкретного реквизита в конфигураторе. Если там установлено значение "Не индексировать", это еще не означает, что индекса в базе данных не существует.
Выясним важную особенность платформы: Критерии отбора. В типовых конфигурациях, таких как "1С:Комплексная автоматизация 2" или "1С:ERP", реквизит Партнер включен в критерий отбора ДокументыПоПартнеру. Когда реквизит попадает в состав любого критерия отбора, система автоматически создает индекс по этому полю в таблице СУБД для оптимизации поиска. Именно поэтому поиск по партнеру происходит мгновенно — СУБД использует готовое индексное дерево.
В то же время реквизит Грузополучатель может не входить ни в один критерий отбора и не иметь явной индексации. В этом случае системе приходится выполнять Table Scan (полное сканирование таблицы). Для базы в 50 000 документов в файловом режиме это занимает значительное время, так как программе нужно прочитать каждую запись с диска, чтобы проверить условие.
Проанализируем влияние файлового режима (формат .1CD). В отличие от клиент-серверного варианта под управлением MS SQL Server или PostgreSQL, файловый движок 1С имеет менее эффективный оптимизатор запросов и кэширование. Если данные по партнерам часто используются в других задачах системы, они могут "осесть" в оперативной памяти (кэше). Данные по грузополучателям, если к ним обращаются редко, считываются непосредственно с жесткого диска, что добавляет задержки ввода-вывода.
Посмотрим на тип данных реквизита. Если Грузополучатель имеет составной тип (например, СправочникСсылка.Контрагенты и СправочникСсылка.Партнеры), то в физической таблице базы данных это поле представлено несколькими колонками (одна для типа, другая для ссылки). Запросы к таким полям без уточнения типа работают медленнее.
Рассмотрим, как можно оптимизировать такой запрос с помощью функции ВЫРАЗИТЬ. Это подскажет системе, с какой конкретно таблицей нужно сопоставлять данные, исключая лишние проверки:
ГДЕ
ЗаказКлиента.ДатаОтгрузки МЕЖДУ &ДатаНачала И &ДатаКонца
И ВЫРАЗИТЬ(ЗаказКлиента.Грузополучатель КАК Справочник.Контрагенты) = &Грузополучатель
И ЗаказКлиента.Проведен = ИСТИНА
Чтобы точно узнать, какие индексы созданы в вашей базе (включая неявные), выполним следующий метод:
Воспользуемся функцией ПолучитьСтруктуруХраненияБазыДанных(). Она вернет таблицу с описанием всех таблиц и индексов на уровне СУБД. Проанализировав колонку ИмяТаблицыХранения и связанные с ней индексы для документа ЗаказКлиента, мы увидим реальную картину.
На основе нашего исследования выделим три основных способа ускорения запроса:
Грузополучатель установим свойство Индексировать в значение "Индексировать". Это создаст индекс и сравняет скорость выполнения второго запроса с первым.[Грузополучатель + Дата], что позволит системе максимально быстро находить документы за конкретный период по конкретному получателю.Дата), а затем наложить фильтр по грузополучателю. Однако, как показала практика обсуждения, на небольших объемах (50к записей) этот метод может быть даже медленнее из-за накладных расходов на создание временной таблицы.Разберем итог: колоссальная разница в скорости возникла из-за того, что поле Партнер было неявно проиндексировано через Критерий отбора, а поле Грузополучатель — нет. После установки свойства Индексировать в конфигураторе время выполнения запроса сокращается до сотых долей секунды. Всегда проверяйте наличие индексов не только визуально в реквизитах, но и через структуру хранения базы данных, особенно в высоконагруженных или крупных информационных системах на базе 1С:Предприятие.