Маркеры оборудования

30.08.24

База данных - HighLoad оптимизация

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

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
Маркеры оборудования:
.epf 8,37Kb
3
3 Скачать (1 SM) Купить за 1 850 руб.

 

История создания

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

Я записал эту идею в свой конспект, который вел при просмотре курса.

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

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

  1. мы разрабатывали корпоративную информационную систему, зоны ответственности которой были поделены между командами, например, команда № 1 отвечала за блок централизованных оплат, команда № 2 за товародвижение и тд.
  2. за каждой командой был закреплен свой профиль ключевых операций, в которым были собраны только критичные для бизнеса операции. Если APDEX достигал заданного уровня (плохо и ниже) и удерживался на нем n периодов подряд, то срабатывал алерт.

Необходимо было написать код для ключевых операций, который бы показывал возможные проблемы на одном из серверов: 1С или СУБД (сервера приложений 1С и СУБД всегда были разнесены по разным машинам, на одной никогда не находились).

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

 

Сервер приложений 1С

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

 

Маркер "СП обход строк ТЗ"

В данном маркере выполнялось 2 действия на стороне сервера приложений:

  1. Выгрузка результата запроса в таблицу значений (250 тысяч записей) - задействуем оперативную память сервера приложений.
  2. Циклический обход таблицы значений с осуществлением операции присвоения значения.

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

 

Запрос = Новый Запрос(
    "ВЫБРАТЬ ПЕРВЫЕ 250000
    |   АвансовыйОтчетТабличнаяЧастьДокумента.Ссылка КАК Ссылка,
    |   АвансовыйОтчетТабличнаяЧастьДокумента.НомерСтроки КАК НомерСтроки,
    |   АвансовыйОтчетТабличнаяЧастьДокумента.Сумма КАК Сумма,
    |   АвансовыйОтчетТабличнаяЧастьДокумента.СтавкаНДС КАК СтавкаНДС,
    |   АвансовыйОтчетТабличнаяЧастьДокумента.СуммаНДС КАК СуммаНДС
    |ИЗ
    |   Документ.АвансовыйОтчет.ТабличнаяЧастьДокумента КАК АвансовыйОтчетТабличнаяЧастьДокумента");
    Результат = Запрос.Выполнить();
     
    КлючеваяОперация = "СП_ОбходСтрокТЗ";
    НачалоЗамера = ОценкаПроизводительности.НачатьЗамерВремени();
     
    ТЗ = Результат.Выгрузить();
    Для каждого СтрокаТЗ Из ТЗ Цикл
        СтрокаТЗ.СуммаНДС = СтрокаТЗ.Сумма;
    КонецЦикла;
     
    ОценкаПроизводительности.ЗакончитьЗамерВремени(КлючеваяОперация, НачалоЗамера);

 

 

Маркер "СП сериализация XML"

Идея данного маркера у меня возникла не просто так. 

В компании "Магнит" есть такой ежегодный процесс как переход на последнюю версию платформы 1С всех информационных систем компании, и во время одного из переходов на конфигурации ЗУП как раз и возникла проблема: сериализация стала утилизировать значительно больше ресурсов сервера приложений 1С. На тот момент я думал, что следующий код как раз и поможет нам в будущем выявлять такие случаи:

 

Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 100
|   АвансовыйОтчет.Ссылка КАК Ссылка
|ИЗ
|   Документ.АвансовыйОтчет КАК АвансовыйОтчет");
 
Выборка = Запрос.Выполнить().Выбрать();
 
КлючеваяОперация = "СП_СериализацияXML";
НачалоЗамера = ОценкаПроизводительности.НачатьЗамерВремени();
 
ЗаписьXML = Новый ЗаписьXML;
ИмяФайла = ПолучитьИмяВременногоФайла("xml");
ЗаписьXML.ОткрытьФайл(ИмяФайла);
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента("data");
Пока Выборка.Следующий() Цикл
    ЗаписатьXML(ЗаписьXML, Выборка.Ссылка.ПолучитьОбъект());
КонецЦикла;
ЗаписьXML.Закрыть();
УдалитьФайлы(ИмяФайла);
 
ОценкаПроизводительности.ЗакончитьЗамерВремени(КлючеваяОперация, НачалоЗамера);

 

Будущее думало иначе: этот маркер действительно показал нам проблему не один раз, но они не были связаны с сериализацией, и позже вы поймете, почему. Либо посмотрите внимательно на этот код и попробуйте понять какие компоненты инфраструктуры, на которой работает информационная база, он еще способен протестировать.

 

Сервер СУБД

Если с сервером приложений маркеры было придумать довольно просто, то с СУБД дела обстояли иначе.

Сервер СУБД – более производительный компонент, чем сервер приложений 1С, и если нужно сделать какие-то ресурсоемкие вычисления, то, конечно, правильно их делать на сервере СУБД.

Поэтому здесь замерять операции типа расчета арифметической операции смысла не имело.

 

Маркер "СУБД выборка бухгалтерских проводок"

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

 

КлючеваяОперация = "СУБД_ВыборкаБухгалтерскихПроводок";
НачалоЗамера = ОценкаПроизводительности.НачатьЗамерВремени();
 
Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 10000
|   Бухгалтерский.Период КАК Период,
|   Бухгалтерский.Регистратор КАК Регистратор,
|   Бухгалтерский.НомерСтроки КАК НомерСтроки,
|   Бухгалтерский.Активность КАК Активность,
|   Бухгалтерский.СчетДт КАК СчетДт,
|   Бухгалтерский.СчетКт КАК СчетКт,
|   Бухгалтерский.Организация КАК Организация,
|   Бухгалтерский.База КАК База,
|   Бухгалтерский.Филиал КАК Филиал,
|   Бухгалтерский.ВалютаДт КАК ВалютаДт,
|   Бухгалтерский.ВалютаКт КАК ВалютаКт,
|   Бухгалтерский.Сумма КАК Сумма,
|   Бухгалтерский.ВалютнаяСуммаДт КАК ВалютнаяСуммаДт,
|   Бухгалтерский.ВалютнаяСуммаКт КАК ВалютнаяСуммаКт,
|   Бухгалтерский.КоличествоДт КАК КоличествоДт,
|   Бухгалтерский.КоличествоКт КАК КоличествоКт,
|   Бухгалтерский.Содержание КАК Содержание,
|   Бухгалтерский.НомерЖурнала КАК НомерЖурнала,
|   Бухгалтерский.МоментВремени КАК МоментВремени
|ПОМЕСТИТЬ ВременнаяТаблица
|ИЗ
|   РегистрБухгалтерии.Бухгалтерский КАК Бухгалтерский
|ГДЕ
|   Бухгалтерский.Период МЕЖДУ &НачалоПериода И &КонецПериода
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
|   ВременнаяТаблица.Период КАК Период,
|   ВременнаяТаблица.Регистратор КАК Регистратор,
|   ВременнаяТаблица.НомерСтроки КАК НомерСтроки,
|   ВременнаяТаблица.Активность КАК Активность,
|   ВременнаяТаблица.СчетДт КАК СчетДт,
|   ВременнаяТаблица.СчетКт КАК СчетКт,
|   ВременнаяТаблица.Организация КАК Организация,
|   ВременнаяТаблица.База КАК База,
|   ВременнаяТаблица.Филиал КАК Филиал,
|   ВременнаяТаблица.ВалютаДт КАК ВалютаДт,
|   ВременнаяТаблица.ВалютаКт КАК ВалютаКт,
|   ВременнаяТаблица.Сумма КАК Сумма,
|   ВременнаяТаблица.ВалютнаяСуммаДт КАК ВалютнаяСуммаДт,
|   ВременнаяТаблица.ВалютнаяСуммаКт КАК ВалютнаяСуммаКт,
|   ВременнаяТаблица.КоличествоДт КАК КоличествоДт,
|   ВременнаяТаблица.КоличествоКт КАК КоличествоКт,
|   ВременнаяТаблица.Содержание КАК Содержание,
|   ВременнаяТаблица.НомерЖурнала КАК НомерЖурнала,
|   ВременнаяТаблица.МоментВремени КАК МоментВремени,
|   БухгалтерскийСубконто.Период КАК Период1,
|   БухгалтерскийСубконто.Регистратор КАК Регистратор1,
|   БухгалтерскийСубконто.МоментВремени КАК МоментВремени1,
|   БухгалтерскийСубконто.НомерСтроки КАК НомерСтроки1,
|   БухгалтерскийСубконто.ВидДвижения КАК ВидДвижения,
|   БухгалтерскийСубконто.Вид КАК Вид,
|   БухгалтерскийСубконто.Значение КАК Значение
|ПОМЕСТИТЬ ВременнаяТаблица2
|ИЗ
|   ВременнаяТаблица КАК ВременнаяТаблица
|       ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Бухгалтерский.Субконто КАК БухгалтерскийСубконто
|       ПО ВременнаяТаблица.Период = БухгалтерскийСубконто.Период
|           И ВременнаяТаблица.НомерСтроки = БухгалтерскийСубконто.НомерСтроки
|           И ВременнаяТаблица.Регистратор = БухгалтерскийСубконто.Регистратор");
ТекДата = ТекущаяДата();
Запрос.УстановитьПараметр("НачалоПериода",  ТекДата - 12*3600);
Запрос.УстановитьПараметр("КонецПериода",   ТекДата);
Запрос.Выполнить();
 
ОценкаПроизводительности.ЗакончитьЗамерВремени(КлючеваяОперация, НачалоЗамера);

 

А логика в следующем:

  1. Прочитать данные именно с диска, а не буферного кэша. Для этого мы выбираем  проводки из регистра бухгалтерии за последние 12 часов с упорядочиванием по возрастанию. Для чтения задействовался именно кластерный индекс MS SQL, в котором данные упорядочены по полю "Период" (данные в Postgres не хранятся в упорядоченном виде, но т.к. в этом случае мы будем читать данные из индекса с полями "Период", "Регистратор", "НомерСтроки", то данные будут отсортированы согласно полям этого индекса, и дополнительно указывать сортировку в запросе необходимости нет). 
  2. Поместить во временную таблицу, чтобы проверить скорость работы tempdb: в первом запросе 10 тысяч записей, во втором – до 50 тысяч (на счетах могло быть до 5 субконто).
  3. Сами выборки данных должны были работать максимально быстро, т.к. точно попадали в условия кластерного индекса основной таблицы и таблицы субконто. Индекс в первой временной таблице по полям "Период", "Регистратор" и "НомерСтроки" не создавался, т.к. записи и так были упорядочены по этим полям, что дает возможность во втором запросе оптимизатору использовать hash join без дополнительной сортировки.

Маркер запускался каждые 5 минут, поэтому за это время каждый раз он должен был читать новые данные. В среднем в рабочее время (с 9 до 18 часов дня) за одну минуту создавалось около 4 тысячи новых проводок в регистре бухгалтерии.

Зачем читаем данные за последние 12 часов? Потому что в нерабочее время интенсивность создания проводок сильно падала, и, если бы мы выбирали, допустим, за 1 час, то проводок могло быть выбрано значительно меньше. А мне хотелось создать равномерные замеры ключевой операции.

 

Маркер "СУБД неоптимальный запрос"

Этот маркер я создал с той целью, чтобы посмотреть как неоптимальный запрос будет вести себя в периоды высокой нагрузки на сервер СУБД:

 

КлючеваяОперация = "СУБД_НеоптимальныйЗапрос";
НачалоЗамера = ОценкаПроизводительности.НачатьЗамерВремени();
 
Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 5000
|   АвансовыйОтчет.Ссылка КАК Ссылка,
|   АвансовыйОтчет.Счет.ПометкаУдаления КАК СчетПометкаУдаления,
|   АвансовыйОтчет.ЦФО.ДатаОткрытия КАК ЦФОДатаОткрытия,
|   АвансовыйОтчет.ДокументОснование.Дата КАК ДокументОснованиеДата
|ПОМЕСТИТЬ ВременнаяТаблица
|ИЗ
|   Документ.АвансовыйОтчет.ТабличнаяЧастьДокумента КАК АвансовыйОтчетТабличнаяЧастьДокумента
|       ЛЕВОЕ СОЕДИНЕНИЕ Документ.АвансовыйОтчет КАК АвансовыйОтчет
|       ПО АвансовыйОтчетТабличнаяЧастьДокумента.Ссылка = АвансовыйОтчет.Ссылка
|ГДЕ
|   АвансовыйОтчетТабличнаяЧастьДокумента.Аналитика1 ССЫЛКА Справочник.МоделиТМЦ
|   И не АвансовыйОтчетТабличнаяЧастьДокумента.Аналитика1 В
|           (ВЫБРАТЬ
|               справочник.моделитмц.Ссылка
|           ИЗ
|               справочник.моделитмц
|           ГДЕ
|               справочник.моделитмц.ПометкаУдаления)
|   И НЕ АвансовыйОтчетТабличнаяЧастьДокумента.Аналитика1.ПометкаУдаления");
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Выполнить();
 
ОценкаПроизводительности.ЗакончитьЗамерВремени(КлючеваяОперация, НачалоЗамера);

 

Все маркеры готовы, теперь поговорим о том какие проблемы они позволили выявить.

 

Примеры выявленных проблем

Когда я создавал эти маркеры, то хотел соотносить их с данными ADPEX ключевых операций бизнеса, чтобы выявлять закономерности в периоды проблем. Вот пример графика маркера:

 

 

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

 

"Магнит": переход на новую версию платформы

Очередной год и мы переходим на новую версию платформы: это был переход на 8.3.19 в 2021 году. После перехода, как обычно, выявляешь какие-то баги, которые не показало тестирование. Все они как правило некритичны, ибо в процессе подготовки перехода проводятся тщательный анализ всех изменений, которые могут повлиять на конфигурации, и не менее тщательное тестирование.

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

И в итоге маркер "СП обход строк ТЗ" показал примерно такую картину:

 

 

Также у одной ключевой операции бизнеса упала производительность ввиду того, что использовались аналогичные конструкции обхода большого количества строк в цикле.

Итого проблему можно сформулировать следующим образом: при включенной отладке код 1С начинал выполняться медленнее, что особо было заметно в обходах цикла с большим количеством итераций.

Проблему отправили на КОРП-поддержку, и в одном из следующих минорных релизов фирма 1С ее оперативно исправила. Не считаю, что она была критичной, ибо, как уже сказал, отладка в продуктиве должна быть выключена. 

А у вас она выключена?

 

"Sunlight": апгрейд продуктивных серверов

В данной компании получился довольно интересный кейс, когда мы осуществляли замену устаревших серверов приложений и СУБД на новые.

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

Маркер "СП сериализация XML" выполнялся в среднем за 1,5 секунды.

Новые сервера были установлены в один из ЦОДов компании, и под сервер СУБД и 1С были развернуты виртуальные машины. Миграцию планировали делать постепенно: сначала заменили сервер приложений, а затем делали смену сервера СУБД.

После смены сервера СУБД начались проблемы: CPU стал утилизироваться под 90%, хотя конфигурация сервера была такая же как и до переезда: 48 CPU и 1,5 Тб ОЗУ. Оказалось, что порог стоимости параллелизма (cost threshold for parallelism) был настроен некорректно, и там стояло значение "5" (дефолтное), из-за чего большое количество запросов пыталось использовать параллельное выполнение узлов плана, и им просто не хватало выделенных на сервере ядер. После того как увеличили это значение до такого, которое было на старом сервере, проблема ушла.

После этого мы посмотрели сервер СУБД с ЕРП, у которого также стоял такой же низкий порог параллелизма. На нем вот такой простейший запрос выполнялся 2 сек. из-за использования параллелизма на операции вставки во временную таблицу:

 

ВЫБРАТЬ ПЕРВЫЕ 10000
    *
ПОМЕСТИТЬ ВТ
ИЗ
    РегистрНакопления.СебестоимостьТоваров

 

Поэтому, если у вас MS SQL, то советую лишний раз посмотреть на указанный выше параметр, если у вас включен параллелизм (в моей практике он был всегда у нас включен на высоконагруженных базах, просто нужно правильно подобрать порог).

Мы немного отвлеклись от нашего маркера. После решения критичной проблемы работа системы пришла в норму, но маркер "СП сериализация XML" стал выполняться в 10 раз дольше – 15 секунд.

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

 

Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 100
|   АвансовыйОтчет.Ссылка КАК Ссылка
|ИЗ
|   Документ.АвансовыйОтчет КАК АвансовыйОтчет");
 
Выборка = Запрос.Выполнить().Выбрать();
 
КлючеваяОперация = "СП_СериализацияXML";
НачалоЗамера = ОценкаПроизводительности.НачатьЗамерВремени();
 
Пока Выборка.Следующий() Цикл
    Выборка.Ссылка.ПолучитьОбъект();
КонецЦикла;
 
ОценкаПроизводительности.ЗакончитьЗамерВремени(КлючеваяОперация, НачалоЗамера);

 

Выполнил – также 15 секунд, т.е. основное время у нас занимает получение объекта.

С точки зрения 1С, получение одного объекта – это серия запросов к базе данных:

  1. Запрос чтения шапки объекта
  2. Отдельный запрос для чтения каждой табличной части (например, 5 табличных частей – 5 запросов)
  3. Запрос чтения версии объекта

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

Результат чтения объекта кэшируется в памяти сервера приложений в течении 20 секунд, поэтому выполнять этот запрос нужно с разницей минимум 20 секунд.

Далее я включил сбор технологического журнала, настроил событие в extended events для сбора информации о времени выполнения запросов и получил результаты: по данным ТЖ запрос выполнялся на порядок медленнее, чем по данным MS SQL (разница была десятки миллисекунд). 

После этого мы вместе с администратором 1С пошли к нашим администраторам Windows, объяснили проблему, и они сказали, что знают причину: трафик между сервером приложений и СУБД ходит по общей сети компании. Не помню, что сказали админы на вопрос, как было раньше и почему сейчас стало так; в итоге проблема была решена тем, что между сервером приложений и сервером СУБД был поднят отдельный канал через технологию jumbo channels, и размером пакета 8 Кб. После этого значение маркера вернулось в нормальное в пределах 1,5–2 секунд.

 

"Тантор Лабс": сравниваем сервера приложений

Следующий кейс был уже связан с моим текущим местом работы, в рамках которого я помогаю клиентам разобраться с возникающими вопросами после миграции на СУБД Tantor.

У клиента было 2 одинаковых физических сервера, на одном из которых были развернуты сервер приложений и сервер СУБД на стеке Windows Server + MS SQL, а на другом сервере – то же самое, но на стеке Astra Linux +Tantor SE 1C.

Тестировалась ключевая операция заполнения документа в ЗУПе, и по замерам времени в конфигураторе были получены результаты, по которым стек на Windows показал результат на 30% лучше.

По замерам производительности оказалось, что не только запросы к БД выполняются медленнее, а вообще любой код выполнялся медленнее в среднем на 20%:

 

(слева Astra Linux, справа Windows)

Но что о таком думают заказчики? Конечно они говорят, что это Postgres плохо работает) И необходимо было наглядно показать, что тут проблема не только в том, что некоторые запросы выполнялись медленнее.

На помощь здесь пришел маркер "СП обход строк ТЗ", который выполняется полностью на стороне сервера приложений. По его замерам, на данных стендах мы получили время выполнения на Windows меньше на 50%: 0.64 сек против 0.91.

Таким образом мы наглядно смогли показать заказчику, что сам сервер приложений 1С работает медленнее. Не могу сказать, как именно влияла инфраструктура на падение производительности, но проблему решило разделение сервера приложений и сервера СУБД на разные машины – после этого время выполнения маркера стало такое же, как на Windows, и сам код тестируемой операции стал выполняться быстрее.

 

"Тантор Лабс": опять сетевая проблема?

Один из клиентов обратился к нам с проблемой медленной работы системы, для сбора информации о проблемных запросах мы попросили у них логи технологического журнала 1С и СУБД.

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

Лог на стороне 1С и СУБД собирался с отбором по длительности более 1 секунды. И при анализе запроса обратила на себя внимание сильная разница во времени выполнения запросов по данным разных логов. Ниже данные о времени выполнения 5 запросов: 

 


1.
Лог 1С: 00:06.015000-15018996
Лог СУБД: 2024-07-30 14:00:06.009 MSK [85924] LOG:  duration: 6864.310 ms  plan:
 
2.
Лог 1С: 00:53.071008-6105003
Лог СУБД: нет в логе, значит выполнялся менее секунды.
 
3.
Лог 1С: 01:44.991003-13328002
Лог СУБД: 2024-07-30 14:01:44.986 MSK [84645] LOG:  duration: 6084.727 ms  plan:
  
4.
Лог 1С: 03:30.152000-15033997
Лог СУБД: 2024-07-30 14:03:30.145 MSK [84645] LOG:  duration: 6329.789 ms  plan:
  
5.
Лог 1С: 14:35.804001-13251000
Лог СУБД: 2024-07-30 15:14:35.796 MSK [94400] LOG:  duration: 6149.201 ms  plan:

 

Как видно из данных, разница в выполнении составляет 7–9 секунд. 

Даем клиенту выполнить маркер "СП сериализация XML", но удалив из него все что связано с сериализацией, получаем среднее время выполнения 4.3 сек, что, по опыту, довольно много, т.к. обычно он выполнялся у меня в диапазоне 1–2 секунд.

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

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

Собираем еще раз логи 1С и СУБД: теперь разница при выполнении стала намного меньше – максимум 100 мс. Клиент отметил, что работать база стала заметно лучше.

Но в логах нашли следующий случай:

 

2024-08-26 11:10:24.276 MSK [25878] LOG:  duration: 2351.584 ms  plan:
    Query Text: SELECT
    ...
    Nested Loop Left Join  (cost=12.34..2549.56 rows=1000 width=437) (actual time=0.914..47.454 rows=1000 loops=1)
    ...

 

Текст запроса я убрал, ибо он чересчур велик.

Смысл в следующем: запрос выполнялся 2361 мс, при этом по плану запроса он выполнился за 47 мс. В запрос в качестве параметра передавался массив из 1000 значений, которые "весят" 72 Кб, если скопировать их в текстовый файл и посмотреть размер этого файла.

Конфигурация была типовая ЕРП, и у меня был контекст выполнения запроса. Я написал обработку, которая выполнит данный запрос дважды: сначала передаст массив из 1000 значений, а потом – из 500.

Перед тем как отдать, я проверил у себя скорость выполнения данного запроса из 1С:

  • массив с 1000 значениями – 20 мс;
  • массив с 500 значениями – 12 мс.

У клиента получаем следующий результат:

  • массив с 1000 значениями – 3400 мс;
  • массив с 500 значениями – 400 мс.

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

Я не являюсь специалистом по сетевой инфраструктуре и ее диагностике, но косвенно через 1С показал клиенту, что у него в инфраструктуре есть проблема. Дальше дело за ним.

 

А что же маркеры СУБД?

Я не помню, чтобы они помогли диагностировать какие-то проблемы. Единственное, когда кто-то пытался делать вставку в tempdb нескольких млрд записей, то маркер 1 это показывал. Но на такие случаи нашими DBA у нас был настроен отдельный мониторинг.

При этом стоит отметить, что смена версии СУБД происходила более сложно, чем смена платформы 1С, т.к. от версии к версии менялась оценка кардинальности, что приводило к тому, что нужно либо переписать часть запросов либо вернуть режим совместимости и старую оценку кардинальности. Мы это испытали при переходе с 2012 на 2016 и с 2016 на 2017 MS SQL, и проблемы были очевидны и без маркеров. 

 

Как встроить обработку в вашу систему

  1. Переписать запросы во всех четырех процедурах, т.к. данные там были подобраны под конкретную информационную систему.
  2. Проверить, что используемые методы начала и фиксации замера производительности соответствуют вашей версии подсистемы "Оценка производительности", входящей в состав БСП. 
  3. Проверьте в режиме "1С:Предприятия", что все 4 маркера отрабатывают корректно, в сообщения выводится время выполнения маркеров.
  4. Настройте в исследуемой базе РЗ, которое по расписанию будет выполнять данную обработку. Самый простой способ – это в конфигурациях с современными версиями БСП добавить обработку в справочник "Дополнительные отчеты и обработки" и настроить регламентное задание на ее основании. Рекомендую выполнять обработку каждые 1 или 5 минут в зависимости от ваших целей.
  5. Последите за работой обработки в течение периода, за который у вас, допустим, будут проблемы в исследуемой системе. Соотнесите проблемы с показаниями маркеров и APDEX, сделайте выводы.
  6. При необходимости настройте алерты на маркеры.

 

Идея для развития

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

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

Для логирования запросов в Postgres нужно установить вот эти 2 настройки:

 

logging_collector = 'on'
log_min_duration_statement = '1000'

 

Заключение

Как мы увидели, эти маркеры можно использовать как диагностическое средство для поиска "узких мест" в инфраструктуре. Я бы вам советовал иметь что-то подобное на постоянной основе, чтобы был ориентир эталонных ключевых операций, которые вы можете оценивать при изменениях внутри вашей инфраструктуры или смене версии платформы 1С или СУБД.

Если проблемы начинаются после изменений в инфраструктуре, то вы сможете наглядно показать вашим коллегам-инфраструктурщикам, что проблема на их стороне, а не в 1С.

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

Также уделяйте особое внимание ситуациям, когда запросы по данным логов 1С и СУБД выполняются значительно разное время, это может свидетельствовать о проблеме где-то между компонентами вашей информационной системы. 

 

 

Александр Симонов, "Тантор лабс".

 

 

 

 

 

Проверено на следующих конфигурациях и релизах:

  • 1С:ERP Управление предприятием 2, релизы 2.5.7.201

Маркеры оборудования 1с эксперт инфраструктурные проблемы сетевые задержки технологический журнал 1С логи СУБД логи postgres mssql postgres tantor магнит sunlight оптимизация запросов

См. также

HighLoad оптимизация Программист Платформа 1С v8.3 Бесплатно (free)

Метод очень медленно работает, когда параметр приемник содержит намного меньше свойств, чем источник.

06.06.2024    8589    Evg-Lylyk    61    

43

HighLoad оптимизация Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Анализ простого плана запроса. Оптимизация нагрузки на ЦП сервера СУБД используя типовые индексы.

13.03.2024    4827    spyke    28    

49

HighLoad оптимизация Программист Платформа 1С v8.3 Бесплатно (free)

Оказывается, в типовых конфигурациях 1С есть, что улучшить!

13.03.2024    7170    vasilev2015    20    

42

HighLoad оптимизация Инструменты администратора БД Системный администратор Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Обработка для простого и удобного анализа настроек, нагрузки и проблем с SQL сервером с упором на использование оного для 1С. Анализ текущих запросов на sql, ожиданий, конвертация запроса в 1С и рекомендации, где может тормозить.

2 стартмани

15.02.2024    11707    223    ZAOSTG    76    

115

HighLoad оптимизация Системный администратор Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Принимать, хранить и анализировать показания счетчиков (метрики) в базе 1С? Почему бы нет? Но это решение быстро привело к проблемам с производительностью при попытках построить какую-то более-менее сложную аналитику. Переход на PostgresSQL только временно решил проблему, т.к. количество записей уже исчислялось десятками миллионов и что-то сложное вычислить на таких объемах за разумное время становилось все сложнее. Кое-что уже практически невозможно. А что будет с производительностью через пару лет - представить страшно. Надо что-то предпринимать! В этой статье поделюсь своим первым опытом применения СУБД Clickhouse от Яндекс. Как работает, что может, как на нее планирую (если планирую) переходить, сравнение скорости работы, оценка производительности через пару лет, пример работы из 1С. Все это приправлено текстами запросов, кодом, алгоритмами выполненных действий и преподнесено вам для ознакомления в этой статье.

1 стартмани

24.01.2024    5198    glassman    17    

40

HighLoad оптимизация Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Встал вопрос: как быстро удалить строки из ТЗ? Рассмотрел пять вариантов реализации этой задачи. Сравнил их друг с другом на разных объёмах данных с разным процентом удаляемых строк. Также сравнил с выгрузкой с отбором по структуре.

09.01.2024    12138    doom2good    49    

71
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. paulwist 30.08.24 11:11 Сейчас в теме
Сами выборки данных должны были работать максимально быстро, т.к. точно попадали в условия кластерного индекса основной таблицы и таблицы субконто. Индекс в первой временной таблице по полям "Период", "Регистратор" и "НомерСтроки" не создавался, т.к. записи и так были упорядочены по этим полям


1. Это заблуждение, что чтение по кластерному индексу возвращает результат в "порядке" кластерного индекса, гарантией порядка записей служит кляуза ORDER BY, всё остальное от "лукавого".

что дает возможность во втором запросе оптимизатору использовать hash join без дополнительной сортировки.


2. Подтверждением того, что записи во временной таблице не упорядочены (по мнению оптимизатора), является соединение hash join для второй выборки.
Если бы временная таблица была упорядочена, то был бы merge join, те вместо того, что бы соединить два упорядоченных набора данных, сервер вынужден тратить ресурсы, что бы строить хэш таблицу, а затем производить left join.

PS статья однозначно полезна, +100 очков в карму :)
2. gzharkoj 518 30.08.24 11:59 Сейчас в теме
(1)
1. Это заблуждение, что чтение по кластерному индексу возвращает результат в "порядке" кластерного индекса, гарантией порядка записей служит кляуза ORDER BY, всё остальное от "лукавого".

В подтверждение можно кстати привести postgres (в статье описано), где кластерный индекс не гарантирует порядок после операций изменений, состояние кластеризации нужно поддерживать. А значит считанные данные без доп сортировки не будут соответствовать порядку кластерного индекса
https://postgrespro.ru/docs/postgrespro/9.5/sql-cluster

Про MS SQL написано, что может ускорить операции сортировки, но что не надо использовать Order by не написано.
https://learn.microsoft.com/en-us/previous-versions/sql/sql-server-2008-r2/ms190639(v=sql.105)
3. Tantor 39 30.08.24 13:48 Сейчас в теме
(1)
1. Это заблуждение, что чтение по кластерному индексу возвращает результат в "порядке" кластерного индекса, гарантией порядка записей служит кляуза ORDER BY, всё остальное от "лукавого".

Покажите на примере с mssql, что это заблуждение.
В статье, приведенной пользователем gzharkoj как раз и говорится о том, что нет смысла указывать сортировку:
An index on the columns specified in the ORDER BY or GROUP BY clause may remove the need for the Database Engine to sort the data, because the rows are already sorted. This improves query performance.

Если бы временная таблица была упорядочена, то был бы merge join

Да, вы правы. Имелся ввиду merge join для mssql. Привык уже, что в постгресе нет его, потому что отключен в настройках
5. paulwist 30.08.24 15:00 Сейчас в теме
(3)
Покажите на примере с mssql, что это заблуждение.


В букваре вендора: Порядок возврата строк в результирующем ORDER BY наборе не гарантируется, если предложение не указано.

Пара простых примеров от Брент Озара Why Ordering Isn’t Guaranteed Without an ORDER BY


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


В статье говорится от том, что если в запросе есть ORDER BY or GROUP BY, то движок MSSQL (Database Engine) может удалить очень дорогую операцию сортировки ( физическая операция Sort в плане запроса ) при выполнении запроса.

Там же
4. gzharkoj 518 30.08.24 14:21 Сейчас в теме
(3)
clause may remove

Но ведь тут написано: "может устранить необходимость" - но не написано, что не надо использовать.
6. Tantor 39 30.08.24 15:51 Сейчас в теме
(4)
Ну мы же с вами практики)
И в моей практике сортировку для этого случая в mssql делать не нужно было.
7. gzharkoj 518 30.08.24 16:12 Сейчас в теме
(6) Я как разработчик и руководитель разработки универсально в таком случаю говорю, что без явной сортировки никакой сортировки нет, это просто надо запомнить как правило. Но вы решаете все-таки другие задачи, не разработки бизнес-логики, а тестирования окружения за счет ожидаемого поведения нагрузки и тут вопросов нет, то есть даже если вдруг поведение изменится и включится сортировка это и будет сигналом, что собственно вам и надо.
Спасибо за публикацию, очень интересно.
Jimbo; Tantor; +2 Ответить
8. user612295_death4321 02.09.24 12:41 Сейчас в теме
Было бы интересно послушать, как Вы применяете данную практику, если у Вас несколько серверов приложений в кластере? ТНФами в нужный сервер роутите ?
9. Tantor 39 02.09.24 14:35 Сейчас в теме
(8) Хороший вопрос.
Когда писал этот инструмент, то не было целью выполнять его на каком-то определенном из серверов кластера. Главная задача показать проблему, а если она есть, то уже идти и смотреть что представляет из себя кластер серверов, как он организован и тд - это уже немного другая задача.
Например, в Магните на рабочий сервер мы выносили конкретные ресурсоемкие процессы, такие как формирование отчетов (программный интерфейс БСП имел общий метод, который можно было вынести через ТНФ), а маркеры выполнялись на центральном, где работали пользователи. Но запускать маркеры на каждом из серверов кластера хорошая идея.
10. Jimbo 10 10.09.24 15:13 Сейчас в теме
(9) Саня молодец и красавчик, полезная статья однозначно.
11. user612295_death4321 17.09.24 17:42 Сейчас в теме
(9) Вдохновился статьей, намаркерил :)

Может быть у Вас еще есть интересные маркеры ?)
12. Tantor 39 18.09.24 10:42 Сейчас в теме
(11) Нет, я выложил все свои, что использовал.
Смогли по маркерам что-то найти в своей системе?
13. user612295_death4321 19.09.24 17:14 Сейчас в теме
(12) Выявил..., причем кстати я маркеры настроил на каждый сервер апп в кластере через ТНФ.

В систему просочился какой то не самый качественный код, который грузил СУБД под 60% (мои триггеры работают на 80%), при этом у маркеров ухудшилась производительность в 1.5-2 раза.

Ну а так как у меня еще используются и инструменты мониторинга СУБД, выявил что 80% всей CPU нагрузки на скуль в этот период времени - это ровно один и тот же запрос.

В общем оставь разработчиков наедине на пару недель в 9 ТБ базе без мониторинга - жди беды)
Прикрепленные файлы:
14. Tantor 39 20.09.24 17:00 Сейчас в теме
(13) Супер!
Ваш график заставил меня вспомнить похожий кейс в санлайте.
База Розница 10 Тб, обмен с другими системами происходит через RMQ, которое выполнялось по расписанию.
И изменение одного запроса, который перестал после этого попадать в индекс, привело к такому вот "колючему графику" на сервере СУБД)
Прикрепленные файлы:
Оставьте свое сообщение