Каждый администратор и разработчик систем на базе 1С:Предприятие рано или поздно сталкивается с загадочным поведением системы: стандартный поиск в форме подбора товаров начинает сильно зависать (вплоть до нескольких минут). При этом, если открыть этот же подбор из нового, еще не записанного документа — всё работает мгновенно. Также мгновенно отрабатывает поиск непосредственно в самом справочнике Номенклатура.
В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем внутренние механизмы платформы 1С и СУБД MS SQL Server, а также предложим пошаговые инструкции по оптимизации и устранению этой ошибки.
Для того чтобы понять причину зависания, давайте проанализируем, как платформа 1С работает с остатками и ценами в форме подбора товаров в этих двух сценариях:
_AccumRegTotals). Это происходит практически мгновенно, так как SQL-серверу не нужно производить промежуточные вычисления._AccumRegChangeRec) за весь промежуток времени до нужной даты. Чем больше документов и движений в вашей базе, тем тяжелее СУБД рассчитывать эти остатки «на лету» в составе сложного запроса динамического списка.Ситуация усугубляется механизмом под названием Parameter Sniffing (чувствительность к параметрам) на стороне MS SQL Server. СУБД кэширует план выполнения запроса. План, построенный для оперативной даты, кэшируется как оптимальный. Но когда тот же запрос выполняется для конкретной даты старого документа, СУБД применяет старый закэшированный план, который для этой даты оказывается крайне неэффективным, что приводит к полному сканированию таблиц (Table Scan) вместо быстрого поиска по индексам (Index Seek).
Очень часто основная задержка происходит не из-за регистра остатков, а при обращении к периодическому регистру сведений ЦеныНоменклатуры через виртуальную таблицу СрезПоследних. Если в метаданных регистра сведений не включена опция «Разрешить итоги: Срез последних», то при запросе данных на прошлую дату платформа строит тяжелейший вложенный запрос с группировками для поиска максимального периода по каждой позиции номенклатуры. На больших базах это гарантированно приводит к зависанию интерфейса.
Рассмотрим подробнее практические шаги, которые помогут вам вернуть былую скорость работы формы подбора товаров.
Одной из частых причин «слома» механизма расчета итогов является наличие в базе документов или записей регистров со случайными будущими датами (например, из-за опечатки оператора или сбоя при импорте данных была записана дата 2029 или 3999 год). Даже одна такая запись заставляет СУБД некорректно строить планы запросов.
Для поиска таких записей выполним следующий запрос в консоли запросов:
ВЫБРАТЬ
ЦеныНоменклатуры.Номенклатура КАК Товар,
ЦеныНоменклатуры.Период КАК НекорректныйПериод
ИЗ
РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
ГДЕ
ЦеныНоменклатуры.Период > &ТекущаяДата
Если запрос вернул строки, необходимо программно или вручную исправить даты этих документов на корректные.
Если в базе давно не выполнялось регламентное обслуживание итогов, СУБД тратит слишком много ресурсов на расчет остатков на историческую дату. Выполним следующие действия:
Если вы работаете в нетиповой или измененной конфигурации (либо хотите оптимизировать типовую через расширение), обязательно проверьте свойства регистра сведений ЦеныНоменклатуры (или аналогичного регистра цен, используемого в подборе):
Давайте зададимся логичным вопросом: зачем нам при подборе товаров в старый документ видеть цены, которые были актуальны на дату этого документа? Ведь мы подбираем товар прямо сейчас, и продавать его будем по актуальным текущим ценам! Получение цен «задним числом» в подборе в 95% случаев не имеет практического смысла.
Проанализируем программный код инициализации подбора. Нам нужно сделать так, чтобы параметры получения цен и остатков всегда устанавливались на текущую дату, независимо от даты документа.
Для этого в общем модуле ПодборТоваровСервер (или в модуле формы подбора) найдем место установки параметров запроса динамического списка и заменим дату документа на текущую дату сеанса. Посмотрим на пример реализации через расширение:
&Вместо("УстановитьПараметрыДинамическогоСписка")
Процедура ИТ_УстановитьПараметрыДинамическогоСписка(ПараметрыПодбора)
// Переопределяем дату на текущую, чтобы СУБД использовала оперативные итоги
Если ПараметрыПодбора.Свойство("ДатаДокумента") Тогда
ПараметрыПодбора.ДатаДокумента = ТекущаяДатаСеанса();
КонецЕсли;
// Вызываем оригинальный обработчик с подмененными параметрами
ПродолжитьВызов(ПараметрыПодбора);
КонецПроцедуры
Этот простой шаг полностью решает проблему зависания, так как СУБД всегда будет мгновенно получать остатки и цены из оперативных итогов, а не рассчитывать их за прошлые периоды.
Если зависание происходит именно в момент ввода четвертого символа в поисковую строку, дело в индексе полнотекстового поиска. При вводе коротких строк (1-3 символа) платформа ищет по простому условию ПОДОБНО, а при вводе более длинных строк задействует полнотекстовый индекс.
Для исправления работы ПТП выполним следующие действия:
Запрос подбора товаров в типовых конфигурациях (например, УТ 11.3 / 11.4) динамически усложняется в зависимости от включенных функциональных опций. Особое влияние на производительность оказывает опция «Использовать упаковки». Если на вашем предприятии учет в упаковках не ведется, обязательно отключите эту опцию в настройках номенклатуры. Это исключит из запроса подбора тяжелые левые соединения (LEFT JOIN) с таблицами упаковок, что существенно облегчит работу планировщика запросов MS SQL Server.
Применяя данные шаги по шагам, вы сможете локализовать причину падения производительности и вернуть пользователям возможность быстрой и комфортной работы с подбором товаров в любых документах.