1с зависает поиск в динамическом списке

Обновлено: 08.07.2024

Запросы в динамических списках

Область применения: управляемое приложение, мобильное приложение.

Методическая рекомендация (полезный совет)

При проектировании динамических списков в формах следует учитывать, что динамические списки предъявляют более высокие требования к скорости выполнения запросов, чем в других случаях (например, в отчетах, в процедурах обработки данных и пр.). Данные в динамических списках непосредственно отображаются пользователю, поэтому скорость вывода и обновления данных является критичной. В данной статье перечислены рекомендации, дополняющие общие сведения по оптимизации запросов (см. группу статей «Оптимизация запросов»).

1. Нужно стараться делать простые запросы для динамических списков. Для этого в первую очередь нужно оптимизировать архитектуру хранения данных, чтобы их было просто отображать в динамических списках.

Пример

В динамическом списке документов-распоряжений на отгрузку нужно вывести состояние отгрузки. Состояние зависит от остатков регистра накопления, и статусов двух документов другого типа.

НЕПРАВИЛЬНО

Пытаться разработать запрос для динамического списка, который будет учитывать всю сложную логику расчета состояния отгрузки.

ПРАВИЛЬНО

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

2. Необходимо выбрать один из трех режимов работы динамического списка:

  • Динамическое считывание данных включено (рекомендуется). Используются запросы, выбирающие записи в количестве приблизительно соответствующем количеству видимых строк в таблице;
  • Динамическое считывание данных выключено, задана не виртуальная основная таблица или одна из следующих таблиц: СрезПервых, СрезПоследних, ЗадачиПоИсполнителю, КритерииОтбора, ДвижениеСубконто. Используются запросы, выбирающие по 1000 записей в буфер на сервере, по мере необходимости данные передаются на клиент. Менее эффективно, чем динамическое считывание;
  • Динамическое считывание данных выключено, основная таблица не задана. Запрос выполняется «как есть». В буфере накапливаются данные, начиная с 1000 записей. Чем ближе к концу списка, тем больше записей. Можно использовать только для заведомо маленьких выборок.

3. При разработке динамического списка следует учитывать что запрос, который фактически будет сформирован к СУБД, зависит от предопределенных настроек отборов, порядка и группировки СКД. В частности это означает, что необходимо рассмотреть индексирование полей:

  • По которым выполняется соединение в запросе;
  • На которые наложены условия в запросе;
  • Выведенных в качестве быстрых отборов;
  • По которым выполняется упорядочивание или предусмотрена группировка;
  • По которым ожидается, что пользователь будет часто упорядочивать (группировать).

При этом не следует индексировать все поля подряд «на всякий случай», так как избыточные индексы создают неоправданную нагрузку при записи данных.

4. Настоятельно не рекомендуется использовать конструкции, «утяжеляющие» запрос:

  • конструкции РАЗЛИЧНЫЕ и СГРУППИРОВАТЬ ПО;
  • конструкции ВЫБОР в предложении ГДЕ или в условиях соединения;
  • упорядочивание по полю, полученному при помощи конструкции ВЫБОР, в том числе и пользовательское.

5.1 Соединяться в запросе следует только с небольшим количеством реальных таблиц (в оптимальном варианте в динамическом списке – только одна таблица, и она назначена основной).

Не рекомендуется выполнять соединения:

  • с большим количеством реальных таблиц. Ориентироваться стоит на количество не более 4 таблиц;
  • с вложенными запросами;
  • с виртуальными таблицами.

5.2. Соединение с виртуальными таблицами допустимо в отдельных случаях, если запрос и архитектура данных удовлетворяют ряду условий:

  • допустимо соединение с виртуальными таблицами СрезПоследних (СрезПервых), если регистр сведений содержит
    заведомо небольшое количество записей. Например, получение текущего курса валют по данным регистра сведений КурсыВалют;
  • при обращении к виртуальной таблице будут использованы хранимые итоги регистра сведений (см. Разрешение итогов для периодических регистров сведений);
  • запрос к виртуальной таблице Остатки будет преобразован платформой в простое чтение хранимой таблицы итогов без группировок (см. Эффективное обращение к виртуальной таблице «Остатки»).

5.3. Временные таблицы в динамических списках следует использовать с учетом требований описанных ниже и в стандарте про использование временных таблиц.

5.3.1. Временные таблицы в динамических списках рекомендуется использовать только тогда, когда они содержат заведомо небольшое количество записей. Иначе их использование неэффективно, т.к. значения временных таблиц в динамическом списке НЕ кешируются, а формируется при каждом считывании данных для заполнения списка.

5.3.2. В частности, если не удается переделать запрос динамического списка, используя виртуальные таблицы с ограничениями (см. п. 5.2), или вообще отказавшись от их использования, то вместо соединения с ними следует использовать соединения с временными таблицами.

5.3.3. Если последний запрос динамического списка выбирает данные только из ранее созданной временной таблицы, то это уже не динамический список и следует перепроектировать его запрос и, скорее всего, метаданные, используемые запросом.

5.4. При учете количества таблиц, участвующих в запросе, необходимо помнить, что обращение к полям «через точку» приводит к неявному соединению с дополнительными таблицами. Подробнее см.: Разыменование ссылочных полей составного типа в языке запросов

5.5. При работе со списком под неполными правами, в которых настроены ограничения доступа к данным (RLS) к таблицам, участвующим в запросе*, также автоматически присоединяются условия ограничения доступа к данным, которые замедляют работу списка. Именно в этом режиме работы следует проверять скорость работы динамических списков.

* примечание: к тем таблицам, к которым предусмотрен RLS в конфигурации.

6. Предусмотреть оптимизацию при работе с полями составного типа

  • При использовании в соединениях, отборах, упорядочивании и других конструкциях составного поля, необходимо чтобы состав типов данного поля определялся только ссылочными типами. Подробнее см.: Ограничения на использование реквизитов составного типа;
  • Если известно заранее, какого типа должно быть получено поле составного типа, то его необходимо выражать.

7. Запрос динамического списка рекомендуется менять «на лету» на более оптимальный, если это возможно.

Например, если изменение настройки позволяет переписать запрос динамического списка так, что он будет обращаться к другим метаданным, что позволит выполняться ему быстрее.

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

8.1. Отказаться от части возможностей динамического списка.

  • От вывода не столь значимой информации, получение которой приводит к усложнению запроса;
  • От реализованных сервисных возможностей по группировке списка.

8.2. Осуществлять вывод данных не в динамический список, а в таблицу или дерево значений.

При этом появятся возможности оптимизации недоступные для динамических списков, такие как использование привилегированного режима и т.п..

Данный способ применим, если выполняется одно из условий:

  • Исходных данных заведомо мало (десятки-сотни записей).
  • Обязательные отборы, накладываемые на список, гарантируют, что данных в один момент времени записей выводится мало.
  • Порционность вывода данных организована другими средствами (вручную), например, как в результатах полнотекстового поиска.

9. В случаях, когда в динамическом списке требуется отображение вспомогательных колонок, по которым не требуется отбирать (в том числе через механизмы поиска), сортировать и группировать, и затруднительно, неэффективно или невозможно выполнить получение данных с помощью основного запроса, рекомендуется воспользоваться обработчиком ПриПолученииДанныхНаСервере таблицы управляемой формы. Например, колонки Курс на сегодня , Кратность в списке валют и т.п.

Для эффективной работы обработчика ПриПолученииДанныхНаСервере следует выбирать всю вспомогательную информацию одним запросом сразу для всех отображаемых строк, которые передаются в этот обработчик после выполнения основного запроса динамического списка.

Кроме того, для корректной работы динамического списка требуется явно ограничить выполнение отбора, сортировки и группировки по вспомогательным колонкам с помощью методов динамического списка УстановитьОграниченияИспользованияВГруппировке , УстановитьОграниченияИспользованияВПорядке и УстановитьОграниченияИспользованияВОтборе .

Доброго дня
у 1 пользователя проблема нарисовалась. Юух. 3. 0 когда в справочнике номенклатура что то ищет по строке поиска - поиск подвисает. Не на всех позициях такое. Но есть. У меня при вводе того же в строке поиска все работает ок.

В ЖР смотрю что происходит у нее.

Фоновое задание. Отмена
Поиск в динамическом списке: Справочник.Номенклатура.Форма.ФормаВыбора.Список

Индекс перезаполнял и очищал.

как то волнами. то норм то зависает. НА серваке все ок.
Если открыть справочник и искать в нем - то не зависает. если через документ искать по части строки - зависает.
когда просто открыт справочник - остатков в нем не отображается, как правило
(3) Волнами - может как раз обновление индекса ППД в этот момент работает?
(8) все началось когда полнотекстовой поиск был отключен .
(0) Бывает. Особенно тормозит на регистре "СоответствияОбъектовИнформационныхБаз". А если при этом сделать быстрый отбор и удалить записи, вот это торможение :)
(12) Почисть у проблемного пользователя КЭШ для начала, настрой обновление ППД пореже поставь, затем отборы какие стоят у пользователя.
Такая фигня в рознице была файловой,очистка папок помогла с базой. Оставляем только файл базы. Но это не точно.

1. При включеном Полнотектовом поиске в платформе 16.. поменяли что то. Ищет по начало слова только. Например если Бух вводит Пласт тв спл. то будут выводиться только ном. позиции типа Пластина тв. Сплав.. Ну и так далее. А раньше когда Полнотекстовый поиск был выключен вводя "Пласт тв спл." выводилось все. : Пластина ТВердоСПЛавная 1312312 и Пластина тв. спл. и тд.

так же может зависнуть при создании новой номенклатуры
(21) это и дураку понятно, что SQL
Можно добавить подробностей, вплоть до номера релиза СУБД ?
(0) Обратил внимание что динамические списки жутко тормозят если юзвери добавляют в списке через изменить форму реквизиты через точку от ссылки

(11) этот регистр не индексируется и в нем 1 поле не определенного вида, если попытатся по нему даже сортировку сделать база может упасть по памяти

(25) через точку надо запрещать, при чем жестко, для этого надо настраивать доступные поля

Методика расследования причин медленной работы операции на примере открытия управляемой формы

Для начала необходимо убедиться, что проблема стабильно воспроизводится (в одинаковых условиях) и что все пункты с описанием применения методики выполнены. Для этого можно сделать следующее:

Сбор и анализ стандартных данных

Разберем пример для операции открытия формы документа "Табель учёта рабочего времени".

Мы организовали тестовый стенд, на котором наша проблема воспроизводится под пользователем с полными правами. К этому стенду мы можем подключаться как напрямую с удаленной рабочей станции в режиме тонкого клиента, так и в режиме веб-клиента через публикацию на веб-сервере.

Настройка технологического журнала на клиенте может быть такой:

Фильтр по имени процесса для нашей задачи избыточен и нужен для того, чтобы в случае ошибочной настройки такого лога на сервере не получить сбор всех событий для серверных процессов, что может занять значительный объем. С другой стороны, при осознанном включении такой настройки на сервере (если клиентские приложения запускаются там же, где может быть развернут и сервер приложений 1С:Предприятие) мы в отдельном каталоге Client_Full увидим данные только клиентских приложений (хотя при этом подкаталоги других процессов тоже будут созданы, но они буду пустыми). Свойство Interface не собираем, так как оно дублируется более "человек читаемым" свойством IName (хотя даже последнее нам в данном примере не обязательно нужно).

После настройки технологических журналов и проверки корректности замера времени ОценкиПроизводительности БСП выполняем повторение операции с включенной отладкой.

Замеры времени средствами БСП будут выглядеть следующим образом:


Везде далее будем рассматривать верхний в этом списке замер от последнего повторения, его длительность 13,022 секунды.

Замер отладчиком конфигуратора изображен на следующем рисунке:


Как видно, сумма длительности всех строк, связанных с открытием формы составила всего 1,523 секунды.

'00010101' + ТекущаяУниверсальнаяДатаВМиллисекундах() / 1000

а для миллисекунд взять остаток от деления на 1000 (то есть просто последние три цифры, обратите внимание на "779" на следующей картинке).


Точное время начала замера (минут:секунд.миллисекунд): 25:10.779


Точное время окончания замера (минут:секунд.миллисекунд): 25:23.801

Найдем теперь записи технологического журнала, соответствующие данному замеру, они будут примерно следующими:


Здесь видно, что соответствующий нашему замеру серверный вызов SCALL завершился примерно за 10,1 секунды, это соответствует интервалу между запросом VRSREQUEST и ответом VRSRESPONSE.
Причем время начала замера почти совпадает с началом вызова, то есть событием VRSREQUEST, что собственно ожидаемо, так как замер БСП начинается на клиенте и должен быть непосредственно перед командой открытия формы. А вот окончание вызова сервера случилось раньше, чем окончание замера, что значит, что эта разница во времени пришлась на часть работы клиентского приложения.

Итак, промежуточный итог по длительностям замеров разными способами показывает соответствие нашей ситуации ограничениям и выполнение неравенства: 1,5 < 10,1 < 13.

Стандартными инструментами не удается увидеть причину проблем низкой производительности работы (открытия) управляемой формы, поэтому воспользуемся следующими помощниками:

  • Отладчик операционной системы: Windows Performance Recorder для сбора метрик и Windows Performance Analyzer для их визуализации и анализа;
  • Анализатор сетевых протоколов Wireshark или прокси-сервер Fiddler Web Debugger.

Установим и запустим Windows Performance Recorder ("C:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit\WPRUI.exe"), укажем настройки:


После того, как их подготовили, перейдем в тонкий клиент 1С, откроем форму списка документов и непосредственно перед воспроизведением проблемной операции запустим сбор данных WPR (кнопка Start).

После открытия формы в тонком клиенте запись можно остановить и открыть ее для анализа. В открывшемся окне найдем по PID 5508 (его можно определить в диспетчере задач ОС или по логам ТЖ) наш тонкий клиент 1С и должны получить примерно следующую картинку:


По данным Windows Performance Analyzer видим, что у нас нет серьезной нагрузки по дискам, а поток тонкого клиента потребляет 100% ЦП на протяжении длительного времени вплоть до завершения замера.

Запомним этот результат и проанализируем траффик.

Запустим Wireshark и повторим проблемную операцию в тонком клиенте 1С:Предприятие с прямым подключением к серверу приложений 1С.

При сборе данных с помощью Wireshark (и отбору по пакетам с сервером-источником равным серверу приложений 1С:Предприятие) запуск открытия формы документа будет выглядеть примерно так:


Здесь каждая такая строка – это пакет (или если точнее, то "кадр", frame), который в свою очередь является частью общего большого пакета поверх протокола TCP (PDU – Protocol Data Unit). Если их сложить, получим пакет около 70 Кб. Стоит обратить внимание, что это будет размер с учётом сжатия, а если без него – то должны получить что-то около 2500 – 3500 Кб данных.

Устанавливаем и запускаем Fiddler, на панели инструментов ищем "Browse", выбираем любимый браузер и запускаем в нем необходимое нам приложение (информационную базу 1С:Предприятие). После запуска переходим в форму списка документов (готовимся воспроизвести сценарий), возвращаемся в Fiddler и включаем сбор траффика (кнопка F12), переходим в браузер и открываем форму документа. После её открытия сбор траффика можно отключить и заняться его анализом. Мы должны получить примерно следующее:


В данном дампе достаточно быстро находится относительно большой пакет искомого размера, выбираем его в списке слева, а в правой части окна переключаемся на страницу Inspectors, выбираем там просмотр заголовков (Headers), и так как у нас пакет является сериализованным json (Content-Type: application/json), то попросим Fiddler десериализовать его для нас.

После этого в окне предпросмотра отобразится древовидная структура ответа (response), которая передается с сервера на клиент и содержит так много данных. Далее нам необходимо проанализировать её и найти наиболее проблемные места. Может помочь кнопка Expand All, которая развернёт все элементы дерева, но это может занять некоторое время. Чтобы его сократить, сначала поймем, что именно нужно искать.

Подведем промежуточный итог:

  • Проблем с медленной работой прикладного кода 1С или запросов нет.
  • Большая часть времени открытия формы состоит из сетевого взаимодействия.
  • Размер пакета с формой подозрительно велик.
  • После получения пакетов имеем высокую утилизацию ЦП тонким клиентом 1С (или веб-клиентом).
  • Потерянное время находится где-то между окончанием/началом работы прикладного кода 1С и сетевой передачей.

Из всех этих пунктов для нас наиболее полезным и требующим дополнительного анализа является тезис "Размер пакета с формой подозрительно велик".
Какие могут быть причины для такой ситуации? В общем случае их несколько:

  • Сама по себе большая и сложная форма с большим количеством экранных элементов и реквизитов. Наверное, редкий и точно не очень правильный случай, лучше такого избегать на этапе проектирования систем.
  • Простая форма, но много данных в реквизитах формы (включая данные объекта), в особенности:
    • Хранилище значения, Строка(0);
    • Большие коллекции (Таблица, Дерево, Список);
    • Произвольный тип (концентрация проблем).

    Так как наша проблема (у вас может быть по-другому) воспроизводится даже при очень небольшом количестве данных в ТЧ, и реквизитов у документа (т.е. объекта формы) совсем не много, то их мы не рассматриваем. Остаются реквизиты формы, не равные основному реквизиту "Объект".

    Среди них находится несколько реквизитов, имеющих произвольный тип. Могут выглядеть так:


    Сопоставляем эти данные с уже собранным ранее замером с помощью конфигуратора, и видим заполнение этих структур достаточно большим количеством элементов (например, можно 5059 в реквизите "СвойстваИзмерений").
    Снова вернемся к дампу траффика в Fiddler и найдем там элемент, отвечающий за параметры формы (response/props). Увидим там примерно следующее:


    И если развернем далее эти элементы, убедимся, что их там несколько тысяч, каждый из которых представляет собой вложенную структуру вида:


    Найдем прикладной код, заполняющий эти параметры, и убедимся, что данных там действительно достаточно много (2-3 Мб), и они представляют собой большое количество сложных вложенных структур.

    Отключив заполнение данных реквизитов, убеждаемся, что проблема с производительностью формы исчезает, что значит, что причина была найдена правильно.

    Выводы и рекомендации

    Длительная работа открытия формы обусловлена сериализацией и десериализацией больших коллекций значений при передаче их между клиентом и сервером.

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

    В следующей таблице приведены результаты таких замеров в нашем примере. Сразу следует оговориться, что не стоит никаким образом рассматривать в ней абсолютные значения, так как это будет зависеть еще и от конфигурации компьютера, сети, версии платформы и многого другого, связанного именно с нашим примером. Для нас же важны зависимости и их характер (линейная, экспоненциальная и т.д.). Предлагаем вам проанализировать их самостоятельно (или даже повторить замеры на актуальной версии платформы в вашей среде).


    Принимая во внимание полученные таким образом данные, можно предложить следующие возможные пути решения:

    Все статистики и индексы абсолютно обновлены + полнотекстовые. В базе только один я, то есть никаких данных не добавляется и не изменяется. Никаких больше фонновых заданий не запущено.

    Вступная часть:

    Все начинается как обычно с маленького вопроса и как обычно перерастает в целый ряд вопросов "почему?".

    У пользователей было замечено частое подвисание ДС (динамический список). Со слов пользователя, крутятся часики и программа замирает.

    Расследование:

    Долго не пришлось искать, поскольку конфигурация давно уже изменена (не типовая на 100%), то кто-то постарался и установил у пользователей автоматическое обновление в 10 секунд, при этом на уровне конфигурации. Если кто не в курсе, это находится здесь:

    Период автообновления

    На этом не все, часики, конечно, мы устранили. Но в процессе поиска и оптимизации долгих запросов на сервисах Гилева, попадаются опять же наши запросы и наш список, но с использованием оператора поиска LIKE "%%", то есть пользователи осуществляли поиск по части строки. А сервис регистрирует какие-то космические цифры от 10 секунд до (кто бы подумал) 600 секунд. Усомниться в сервисе нет причин, проверено запросом в процессе работы пользователей:

    Я понимаю вашу терпеливость и жажду "запрос в студию", но, обещаю, мы к этому обязательно подойдем, и они еще успеют надоесть :)

    Ну вот, почти добрались, запускаем первую трассировку по ДС. Я для себя сделал открытие, ну я в принципе понимал модель работы ДС, но никогда не видел этого на уровне трассировки. Так вот, на этом уровне к базе идет четыри похожих запроса, разница между ними только в условиях. Для проверки приложил их тексты отдельно (Query1.txt - Query4.txt). Кстати, когда открыть список на форме впервые, то запрос будет только один.

    Запросы ДС

    Здесь, как видим, нет никаких операторов LIKE. Собственно, это правильно, поскольку это просто обновили список без условий. А теперь представляем ту ситуацию, что была прежде, уровень автообновления 10 секунд и поиск по части строки, который работает крайне интересно. То есть мы уже приблизились к тому, что нагружает сервер СУБД. Забегая наперед, сейчас вообще думаем у части пользователей поубирать автообновления ДС, зачем нагружать сервер лишними пакетами запросов.

    Жирный план

    После экспериментов на реквизиты, по которым делали пользователи поиск, накладываем Индексировать с доп. упорядочиванием, чем-таки вырываем частичную победу в производительности:

    Первый план

    Читайте также: