Как оптимизировать запрос к регистру «Версии объектов» и ускорить работу панели «Текущие дела»?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей IT и автоматизация бизнеса
← На главную

Многие разработчики и администраторы систем на базе 1С:Предприятие 8.3, использующие типовые конфигурации (такие как УТ 11, ERP или КА), сталкиваются с периодическими «зависаниями» при входе пользователей в систему. Одной из причин часто оказывается работа стандартной подсистемы «Текущие дела», которая обращается к регистру сведений ВерсииОбъектов. В этой статье мы подробно разберем, почему стандартный запрос может выполняться по 20 и более секунд, проанализируем планы выполнения на уровне СУБД и рассмотрим несколько стратегий оптимизации.

Анализ проблемы: почему стандартный механизм дает сбой

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


ВЫБРАТЬ
    ЕСТЬNULL(СУММА(ВерсииОбъектов.РазмерДанных), 0) КАК РазмерДанных,
    ЕСТЬNULL(СУММА(1), 0) КАК КоличествоВерсий
ИЗ
    РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
ГДЕ
    ВерсииОбъектов.ЕстьДанныеВерсии
    И (ВерсииОбъектов.Объект ССЫЛКА Справочник.Номенклатура И ВерсииОбъектов.ДатаВерсии < &Граница1
    ИЛИ ВерсииОбъектов.Объект ССЫЛКА Документ.ЗаказКлиента И ВерсииОбъектов.ДатаВерсии < &Граница2)

Когда типов объектов становится много, условие ГДЕ разрастается в огромную конструкцию с множеством ИЛИ. Для оптимизатора СУБД SQL Server такой запрос становится «тяжелым» из-за сложности эффективного использования индексов при наличии множественных условий по разным типам ссылок и диапазонам дат одновременно.

Разбор плана выполнения: Seek или Scan?

Проанализируем ситуацию, когда в консоли запросов всё работает быстро, а в технологическом журнале (ТЖ) мы видим длительные события DBMSSQL. Выясним причину, изучив план запроса (Execution Plan). Основная проблема часто кроется в операторе Clustered Index Seek, который на самом деле ведет себя как Scan.

Разберем, почему это происходит:

  1. Разделители данных: Если база работает в режиме разделения (например, в облаке), первым полем в индексах идет _Fld706 (Область данных). СУБД делает быстрый «поиск» (Seek) по этому полю, но дальше вынуждена сканировать миллионы строк, чтобы проверить соответствие полей _Fld13530_TYPE (Тип объекта) и _Fld13530_RTRef (Ссылка на таблицу объекта).
  2. Residual I/O (Избыточное чтение): Поскольку запрос агрегирующий (использует СУММА), СУБД должна прочитать значения из поля РазмерДанных. Если этого поля нет в индексе, SQL Server обращается к основной таблице (Clustered Index), что при объеме регистра в несколько миллионов записей вызывает колоссальную нагрузку на дисковую подсистему и память.
  3. Недостаток памяти: При обработке 2-3 миллионов строк для расчета суммы, СУБД может не хватить выделенной оперативной памяти (Memory Grant), из-за чего данные сбрасываются в TempDB. Это мгновенно увеличивает время выполнения запроса с долей секунды до десятков секунд.

Вариант оптимизации №1: Использование UNION ALL

Один из классических приемов оптимизации сложных запросов с ИЛИ — это разделение их на несколько подзапросов, объединенных через ОБЪЕДИНИТЬ ВСЕ. Это позволяет СУБД построить отдельный эффективный план для каждого типа объекта. Рассмотрим пример преобразованного запроса:


ВЫБРАТЬ
    СУММА(Версии.РазмерДанных) КАК РазмерДанных,
    СУММА(Версии.КоличествоВерсий) КАК КоличествоВерсий
ИЗ (
    ВЫБРАТЬ
        СУММА(ВерсииОбъектов.РазмерДанных) КАК РазмерДанных,
        1 КАК КоличествоВерсий
    ИЗ
        РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
    ГДЕ
        ВерсииОбъектов.ЕстьДанныеВерсии 
        И ВерсииОбъектов.Объект ССЫЛКА Справочник.Номенклатура 
        И ВерсииОбъектов.ДатаВерсии < &Граница1
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        СУММА(ВерсииОбъектов.РазмерДанных),
        1
    ИЗ
        РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
    ГДЕ
        ВерсииОбъектов.ЕстьДанныеВерсии 
        И ВерсииОбъектов.Объект ССЫЛКА Документ.ЗаказКлиента 
        И ВерсииОбъектов.ДатаВерсии < &Граница1
) КАК Версии

Важный нюанс: Хотя этот метод делает планы запросов более предсказуемыми, он может не решить проблему кардинально, если в таблице все еще слишком много данных и отсутствуют подходящие индексы.

Вариант оптимизации №2: Создание покрывающего индекса на уровне SQL

Если правка кода конфигурации затруднена, можно прибегнуть к административным мерам на уровне СУБД. Выясним, какого индекса не хватает системе. Часто СУБД сама подсказывает решение в Missing Index Details. Нам необходим индекс, который позволит СУБД получить все нужные данные (включая размер), не обращаясь к самой таблице.

Рассмотрим пример создания такого индекса (названия полей могут отличаться в зависимости от версии метаданных):


CREATE NONCLUSTERED INDEX [IX_ВерсииОбъектов_Optimization] 
ON [dbo].[_InfoRg13529] ([_Fld18641], [_Fld706]) 
INCLUDE ([_Fld13530_TYPE], [_Fld13530_RTRef], [_Fld13534], [_Fld18639])

Где:

Такой индекс называется покрывающим. С его помощью SQL Server выполнит Index Only Scan, что на порядок быстрее обращения к тяжелым страницам данных, где хранятся сами двоичные образы версий объектов.

Вариант оптимизации №3: Архитектурный подход (Фоновый расчет)

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

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

Если вы используете старую версию УТ (например, 11.3), вы можете самостоятельно внедрить подобный механизм, создав небольшую обработку, которая будет считать итоги и записывать их в константу или отдельный регистр.

Рекомендации по обслуживанию

Помимо оптимизации кода и индексов, не забывайте о регламентных операциях в SQL Server:

Подведем итог: оптимизация работы с версиями объектов требует комплексного подхода — от упрощения логики запроса в 1С до настройки специфических индексов на стороне SQL Server. Наилучший результат дает сочетание покрытия индексами и переход на фоновый расчет данных для пользовательского интерфейса.

← На главную