Клиент обратился с проблемой неработающего обмена с сайтом.
В своей работе Заказчик использует информационную систему на основе «Управление торговлей ред. 11». Конфигурация регулярно выполняет обмен с сайтом. Обмен осуществляется через XML файлы и происходил очень долго. При выгрузке данных для сайта клиент столкнулся с тем, что скрипт загрузки со стороны сайта не успевал обработать выгруженные данные.
Чтобы улучшить ситуацию, Заказчик своими силами разбил выгрузку на порции. Но это не принесло полного решения проблемы.
Чтобы решить проблему, заказчик пригласил меня.
Если Вы не сталкивались с методами повышения производительности раньше, то отмечу, что так или иначе все сводится к нахождению «избыточной работы» и устранению ее.
Проблема оказалась комплексной. Со стороны 1С при выгрузке в файлы попадала избыточная информация. Т.е. передавалось больше данных, чем потом реально использовалось. А со стороны сайта модуль загрузки выполнял лишние действия.
Кроме этого, сама выгрузка, даже по небольшому количеству товаров, занимала длительное время.
Чтобы понять, «какая деятельность лишняя», нужно посмотреть максимально подробно, из чего состоит вся процедура выгрузки данных.
Замер производительности «отладчиком» операции «выгрузки» показал следующее распределение длительности между операциями. 80% времени выполнялся запрос, собирающий данные для выгрузки. Мне повезло, так как 80% времени означает, что если улучшить этот запрос, то можно не прилагать много усилий к другим операциям, ведь эффект на всю выгрузку будет виден сразу. Еще 14% процентов замера выгрузки проверялось какое-то условие. Возможно, на результаты замера свое влияние оказала посторонняя нагрузка (замер выполнялся не «в чистых условиях», на сервере работали и другие пользователи), но этот замер дал представление о проблеме.
Самой простой проблемой оказалось условие «Если». Полностью условие выглядело так:
Если Параметры.РежимПошаговойВыгрузки
И НЕ Параметры.ВыгружатьКраткийПакетПредложенийВРежимеИзменений
И НеОпределено = ВыгруженныеТовары.Найти(Параметры.ВыборкаЦен.Номенклатура) Тогда
Проблема заключалась в выражении ВыгруженныеТовары.Найти(Параметры.ВыборкаЦен.Номенклатура)
Здесь ВыгруженныеТовары — это массив позиций номенклатуры, выгружаемой на текущем шаге. Количество элементов задается в параметрах выгрузки и составляет 400. То есть количество невелико.
Данные этого массива в процедуре никак не использовались, поэтому было решено заменить массив на соответствие. Соответствие представляет собой индексированную коллекцию, и поиск по ней выполняется очень быстро.
В качестве ключа использовал ссылку на номенклатуру, а значение «Истина». После доработки условие стало выглядеть так:
Если Параметры.РежимПошаговойВыгрузки
И НЕ Параметры.ВыгружатьКраткийПакетПредложенийВРежимеИзменений
И НеОпределено = ВыгруженныеТовары[Параметры.ВыборкаЦен.Номенклатура] Тогда
и общее время по этому выражению составило 34 секунды.
Количество повторений этого фрагмента определяется исходным алгоритмом.
Вторым проблемным фрагментом по замеру является запрос, выполняющий сбор данных для выгрузки.
МассивРезультатовЗапроса = Запрос.ВыполнитьПакет();
В данном замере время его выполнения составило более 8 часов. Запрос представляет из себя пакет из более 30 запросов.
Часть данного запроса получается на основе схемы компоновки данных с применением отборов. Отбор накладывается по номенклатуре по условию «в группе». При компоновке макета компоновщик, по возможности, добавляет в результирующий запрос условия, соответствующие отбору.
Например, запрос такого вида:
ВЫБРАТЬ РАЗРЕШЕННЫЕ
СвободныеОстаткиОстатки.Номенклатура КАК Номенклатура,
СвободныеОстаткиОстатки.Характеристика КАК Характеристика,
СвободныеОстаткиОстатки.ВНаличииОстаток КАК ВНаличииОстаток,
СвободныеОстаткиОстатки.ВРезервеОстаток КАК ВРезервеОстаток
ПОМЕСТИТЬ ВремОстатки
ИЗ
РегистрНакопления.СвободныеОстатки.Остатки() КАК СвободныеОстаткиОстатки
после применения отбора примет такой вид:
ВЫБРАТЬ РАЗРЕШЕННЫЕ
СвободныеОстаткиОстатки.Номенклатура КАК Номенклатура,
СвободныеОстаткиОстатки.Характеристика КАК Характеристика,
СвободныеОстаткиОстатки.ВНаличииОстаток КАК ВНаличииОстаток,
СвободныеОстаткиОстатки.ВРезервеОстаток КАК ВРезервеОстаток
ПОМЕСТИТЬ ВремОстатки
ИЗ
РегистрНакопления.СвободныеОстатки.Остатки(,Номенклатура В ИЕРАРХИИ (&П)) КАК СвободныеОстаткиОстатки
После компоновки данных это условие добавилось к нескольким запросам с полем номенклатура. Данное условие плохо сказывается на скорости выполнения запросов.
Чтобы решить эту проблему, в исходный запрос схемы компоновки данных добавил запрос выборки номенклатуры во временную таблицу. И уже данные этой таблицы использовал в качестве фильтра в последующих запросах. Также настроил схему компоновки данных таким образом, чтобы отбор по номенклатуре применялся только для добавленного запроса выборки номенклатуры. После этих манипуляций результирующий запрос принял такой вид (фрагмент):
ВЫБРАТЬ
Номенклатура.Ссылка
ПОМЕСТИТЬ втНоменклатура
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Ссылка В ИЕРАРХИИ(&П)
;
ВЫБРАТЬ РАЗРЕШЕННЫЕ
СвободныеОстаткиОстатки.Номенклатура КАК Номенклатура,
СвободныеОстаткиОстатки.Характеристика КАК Характеристика,
СвободныеОстаткиОстатки.ВНаличииОстаток КАК ВНаличииОстаток,
СвободныеОстаткиОстатки.ВРезервеОстаток КАК ВРезервеОстаток
ПОМЕСТИТЬ ВремОстатки
ИЗ
РегистрНакопления.СвободныеОстатки.Остатки(,Номенклатура В (ВЫБРАТЬ т.Ссылка ИЗ втНоменклатура как т)) КАК СвободныеОстаткиОстатки
Также анализ запроса выявил и другие причины его медленного выполнения:
- Соединение с подзапросами
- Отсутствующие или неоптимальные индексы
- Излишняя выборка данных
В общем, классика жанра.
Решив данные проблемы в комплексе, удалось сократить время выполнения результирующего запроса при полной выгрузке до 78 секунд.
Говоря об оптимизации в теоретическом контексте, часто забывается, что в реальной жизни любая коммерческая работа должна быть рентабельна. Несколько запросов пакета еще имели потенциал для ускорения, но полученный результат полностью устроил клиента, и на этом мы остановились.
После оптимизации время полной выгрузки не превышает 5 минут. Время выгрузки тестовой группы из 15 товаров – несколько секунд (до оптимизации –1.5 минуты).
Заказчик остался очень доволен и сказал много теплых слов. Всегда приятно не просто сделать хорошо работу, но и услышать слова благодарности.
Надеюсь, мой опыт пригодится Вам, и Вы тоже сможете помочь решить подобные проблемы.
С уважением, Гилёв Вячеслав