Адекватный параллелизм в 1С

13.08.21

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

Параллелизм ускоряет выполнение тяжелых регламентных операций на СУБД, но может негативно влиять на работу многопользовательских учетных систем. О том, как анализировать влияние параллелизма и настраивать его для MS SQL и PostgreSQL, рассказал ведущий разработчик компании ООО МКК «Ваш Инвестор» Вадим Фоминых.

 

 

Многие слышали сказку про Золушку.

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

Кроме мачехи в сказке есть противные сестры, которые подначивают Золушку и саботируют ее работу. Но если бы они помогли Золушке – вклинились в процесс перебора и сортировки – ее задачи были бы решены быстрее.

 

 

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

Cost = M * N * Log(N)

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

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

 

 

Небольшой пример из жизни: у нас есть MS SQL и есть PostgreSQL. Нужно выполнить запрос – прочитать 10 млн записей из регистра сведений.

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

Значения в примере приведены для идеальных условий – они соответствуют ситуации, когда мы зашли в базу в монопольном режиме (в базе больше никого из пользователей нет) и сформировали запрос, а потом увеличили MaxDOP (или количество воркеров на Postgres) и получили результат, который нас устраивает.

 

 

Однако большинство компаний, от среднего до крупного бизнеса, почему-то ведут себя как Золушка – не используют параллелизм:

  • на MS SQL у них установлен MaxDOP=1 (максимальная степень параллелизма равна единице, т.е. параллелизм не используется) либо стоит сильно завышенное значение cost threshold for parallelism (настройки порога стоимости для параллелизма);

  • а на PostgreSQL стоит нулевое количество воркеров для обработки узла
    max_parallel_workwrs_per_gather = 0.

Почему так происходит? Почему бы не включить параллелизм? Чтобы понять, как это происходит, нужно заглянуть под капот и узнать, как выглядит механизм параллелизма на СУБД MS SQL и PostgreSQL.

 

План доклада

 

 

Не хотелось бы устраивать жаркой битвы между СУБД MS SQL и PostgreSQL, потому что использование той или иной СУБД – выбор каждого, надо использовать ту СУБД, которую хорошо знаешь.

Поэтому попробуем рассмотреть особенности использования параллелизма в обоих СУБД. Но поскольку время у нас ограничено, а тема параллелизма достаточно широкая, будем брать только ключевые вещи:

  • я покажу, что влияет на параллельное выполнение запросов;

  • какие настройки в MS SQL и Postgres включают параллелизм;

  • покажу примеры использования параллелизма;

  • и подведем итоги.

 

Что заставило меня разобраться с настройками параллелизма

 

 

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

К этому были следующие предпосылки:

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

  • Второй момент – с регламентами обслуживания на СУБД все было очень грустно – они просто не успевали выполняться во время технологического окна, которое составляло порядка 4-6 часов. У нас на тот момент было три базы размером около 150 Гб. Вроде не очень много, но почему-то регламенты в них не доходили до финала и завершались с ошибками.

  • Самое страшное – во время работы пользователей была колоссальная нагрузка на ЦПУ – порядка 93%. И это при том, что одновременно работало не так много пользователей (порядка 110) плюс крутилось небольшое число фоновых заданий, которые выполняли определенную работу.

 

 

Такая нагрузка на ЦПУ меня насторожила, и я решил проверить гипотезу, связанную с простоем, нехваткой процессорного времени.

  • Первым делом я заглянул в настройки СУБД – как ни крути, там все просто. Я сразу обратил внимание на первичные настройки по памяти, по процессорам (affinity mask) и определенные дополнительные настройки. Как раз в дополнительных настройках было выставлено MaxDOP = 0 (использовать все доступные процессоры).

  • Второе – в момент пика нагрузки я запустил скрипт, который показан на слайде:
    select max([runnable_tasks_count]) as [runnable_tasks_count]
    from sys.dm_os_schedulers
    where scheduler_id<255;
    и посмотрел количество ожидающих исполнителей, которые ждут исполнения задания. Это количество варьировалось от 10 до 15 и больше – это тревожный признак, который означал, что для выполнения определенных инструкций операторов запроса процессы, которые их выполняют, находились в режиме ожидания.

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

 

 

Виновники были выявлены быстро – в топ-листе самых долгих запросов по CPU Time и Duration оказались запросы внутри фоновых заданий.

Был еще один момент, который подсказывал, что параллелизм был чрезмерным: CPU Time было значительно больше Duration. CPU Time – это суммарное время, которое складывается из времени каждого ядра, которое выполняет инструкцию запроса.

 

 

Проблема была решена комплексно:

  • Первое, что бросилось в глаза – была проблема с непопаданием в индексы, поэтому мы применили рефакторинг запросов, которые использовались в фоновом задании.

  • Второй момент – очень сильно тянуло выставить MaxDOP=1, но это было для меня слишком просто, поэтому я принял решение чуть-чуть завысить значение cost threshold for parallelism (порога срабатывания параллелизма) до 50 и ограничил MaxDOP до 4.

Картина значительно изменилась, стало гораздо лучше. Это можно увидеть на графике.

 

 

Со временем у нас появился Postgres – мы начали использовать эту СУБД для «Системы взаимодействия» и других баз, которые не являются базами 1С. Мы решили разделить:

Мы решили разделить «мух от котлет»: 1С – это одна область, а Postgres – это другая область. Это дает нам определенный профит: мы можем использовать запросы, которые заточены для Postgres – например, обращаться к данным и индексам, которые хранятся в формате json.

На Postgres у нас затюнены запросы, и в принципе, нет большой многопользовательской нагрузки, но, тем не менее, мы там используем параллелизм.

Есть некоторые вещи, на которые мы натыкались, и это я тоже продемонстрирую на примерах.

 

Немного истории

 

 

По-хорошему, параллелизм есть и в MS SQL, и в Postgres. Но в MS SQL параллелизм появился в 1998 году, в PostgreSQL – в 2016 году, разница в возрасте составляет 18 лет.

Характер поведения параллелизма в MS SQL и в Postgres разнится.

  • Если в MS SQL параллелизм включается на каждый чих – любой запрос с небольшой оценкой стоимости начинает параллелиться.

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

 

Настройки для параллелизма в MS SQL

 

 

В MS SQL у нас есть две ключевые настройки:

  • MaxDOP (max degree of parallelism) – количество процессов, которые запускаются при обработке команды;

  • cost threshold for parallelism – стоимостная оценка, при которой оптимизатор запросов начинает анализировать предварительный план в случае обычного запуска и параллелизма, и выбирает, что ему выгоднее использовать.

Ключевая особенность MS SQL в том, что для применения настроек не нужно перезапускать какие-либо службы, можно использовать скрипт:

EXEC sp_configure 'show advanced options', 1; GO RECONFIGURE WITH OVERRIDE;
GO EXEC sp_configure 'max degree of parallelism', 16;
GO RECONFIGURE WITH OVERRIDE; GO

 

 

Еще небольшая особенность – мы можем задавать MaxDOP не только для СУБД в целом, мы можем указывать MaxDOP для конкретной базы и для индекса.

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

Обратите внимание на возможность выставления MaxDOP для индекса – это очень крутая штука, которую можно использовать в работе.

 

Настройки для параллелизма в PostgreSQL

 

 

В Postgres настроек немного больше, но не все нужно трогать. Есть ключевые настройки.

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

  • Затем оптимизатор проверяет параметр max_parallel_workers – смотрит, сколько всего может выполняться параллельных воркеров, а в конце – параметр max_worker_processes (сколько воркеров в системе доступно). Исходя из этой комбинации, у нас будет запущен параллелизм или не будет.

  • parallel_setup_cost (parallel_tuple_cost) – стоимостная оценка, при которой стартует параллелизм. О том, как эта оценка высчитывается: есть неплохое видео от Олега Иванова с конференции HighLoad. Там все достаточно хорошо объяснено.

  • min_parallel_table_scan_size (min_parallel_index_scan_size) – параметры, связанные со сканированием таблиц и индекса. Опираясь на них тоже будет определяться: нужно нам запускать параллелизм или нет.

    • По умолчанию для параметра min_parallel_table_scan_size стоит 8 МБ. Если размер таблицы гораздо больше – например, если при скане таблицы будет затрачено 24 МБ на выборку (там идет кратность 3), будет подключаться дополнительный воркер на то, чтобы обработать этот участок.

    • Для параметра min_parallel_index_scan_size значение гораздо меньше: 512 килобайт, но там все зависит от страниц – при перечислении 64 страниц мы это значение превысим, будет также подключаться дополнительный воркер, который обеспечит параллельную обработку.

  • Параметром enable_parallel_append мы можем включить параллелизм для соединения двух запросов операцией «ОБЪЕДИНИТЬ» или «ОБЪЕДИНИТЬ ВСЕ». Если этот параметр отключен, конструкции такого вида на Postgres не будут параллелиться. По умолчанию, включен (установлен в ON).

  • enable_parallel_hash – параллельная сборка по хэшу. По умолчанию тоже включен (установлено значение ON).

  • Есть параметр force_parallel_mode – сейчас всегда по умолчанию в OFF. Его можно принудительно включить в ON, и оптимизатор запросов будет вести себя по-другому – он будет на каждый чих пытаться все распараллелить, почти все операции будут уходить в параллелизм. Данную настройку ни в коем случае нельзя включать на продакте, потому что будут проблемы поведения – в параллелизме все-таки есть определенные минусы, о которых я чуть позже расскажу.

Применяются настройки либо перезапуском службы:

service postgresql restart

Либо можно применять команду alter system, где указать определенное количество воркеров на узел и перезагрузить конфигурацию:

alter system set max_parallel_workers_per_gather=N;
select * from pg_reload_conf();

 

Что параллелится и не параллелится в MS

 

 

В MS хорошо параллелятся:

  • Сканы индексов и таблиц, если используется дополнительная последующая агрегация – например, подсчет количества COUNT() с группировкой GROUP BY (СГРУППИРОВАТЬ ПО).

  • Объединение запросов – операторы ОБЪЕДИНИТЬ и ОБЪЕДИНИТЬ ВСЕ параллелятся достаточно хорошо.

  • Реструктуризация базы данных. Начиная с 8.3.11 был изменен механизм в платформе, когда мы не создаем новую таблицу, перенося туда данные, а просто говорим alter table и формируем новую структуру колонок и делаем rebuild index. В этом случае проверяем себя: есть профит: 60-69%, но точно есть.

  • Группировка наборами и конструкция «ВЫРАЗИТЬ» тоже достаточно хорошо параллелятся на MS SQL.

  • Формирование временных таблиц (операция ПОМЕСТИТЬ ВТ) на MS SQL параллелится, но в PostgreSQL есть свои особенности: он там не параллелится.

  • Соединение таблиц.

    • Хорошо параллелится соединение двух отсортированных наборов таблиц, которые получены из покрывающих индексов.

    • На удивление хорошо параллелятся вложенные запросы, если имеет место наследование индексов.

 

 

Из того, что не параллелится – таких ситуаций на MS SQL значительно меньше.

  • При использовании конструкции TOP в некоторых случаях параллелизм может отключаться.

  • Сканирование без агрегации не параллелится и на MS SQL, и на Postgres, потому что проще выбрать все из таблицы, просканировав ее, чем разбивать все на определенные потоки, и потом собирать их.

  • Автоматический режим блокировок (SERIALIZABLE) тоже отключает полностью параллелизм.

 

Что параллелится и не параллелится в Postgres

 

 

В Postgres количество операторов и конструкций, которые параллелятся, немного меньше. Здесь практически то же самое, что в MS SQL:

  • сканы индексов таблиц с последующей агрегацией;

  • объединения запросов;

  • соединение таблиц, особенно merge join;

  • реструктуризация базы данных 2.0 – тоже есть профит, при включенном параллелизме наблюдается положительный эффект. Причем, если говорить о битве MS SQL и PostgreSQL, разница по времени небольшая – если оценивать процентное соотношение, если в MS SQL мы выходили на 60-69%, то в Postgres 60-62% – это достаточно неплохо.

 

 

Что, к сожалению, не параллелится в PostgreSQL:

  • группировка наборами;

  • использование конструкции «ВЫРАЗИТЬ» в запросе;

  • сканирование без агрегации;

  • временные таблицы (использование ПОМЕСТИТЬ ВТ) – грусть и печаль. Они не параллелятся – не знаю, почему. На MS SQL это хорошо работает, возможно, позже это введут и в Postgres.

  • полное внешнее соединение;

  • режим автоматических блокировок (SERIALIZABLE) тоже полностью отключает параллелизм на СУБД в конкретном запросе.

 

Инструментарий

 

 

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

Запросы я буду показывать на MS SQL и PostgreSQL, но поскольку у меня всего одна лицензия, я не буду одновременно запускать два клиентских контекста:

  • запросы к MS SQL я буду выполнять из профайлера – мы будем обращаться к конкретной базе и считывать данные из таблиц 1С;

  • а вот запросы в PostgreSQL мы будем вызывать из контекста 1С.

В случае с MS SQL мы можем:

  • мониторить план запроса через Profiler или Extended Events;

  • анализировать количество ожиданий CXPACKET;

  • писать определенные скрипты, которые получают топы запросов 1С, и сравнивать для них CPU Time с Duration.

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

 

Анализ параллелизма с помощью Profiler для MS SQL

 

 

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

 

 

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

План запросов в MS SQL, который использует параллелизм, отличается:

  • во-первых, появляется оператор Gather – ярлычок со стрелочками, который указывает на включение параллелизма,

  • во-вторых, в окне свойств видно, что оператор Clustered Index Scan будет выполняться параллельно (Параллельный – True)

  • в-третьих, можно раскрыть фактическое число строк, которое было выбрано, и увидеть, что оно было распределено по потокам – плюс-минус порции равны. Обратите внимание, что включен MaxDOP=4, но у нас используется 5 потоков. Нулевой поток используется для того, чтобы собирать все данные и подавать правильные команды на операторы – это следящий поток.

Механика получения данных справа налево ничем не отличается от непараллельных запросов, у нас лишь добавляется оператор Gather, который объединяет информацию со всех потоков и передает ее на клиентский контекст.

 

 

Группировка по наборам (операция СГРУППИРОВАТЬ ПО ГРУППИРУЮЩИМ НАБОРАМ – GROUPING SETS) – здесь используется больше операторов параллелизма.

  • Сначала происходит выборка, она распределяется по потокам. Затем она попадает на оператор параллелилизма Repartition Streams – это оператор пераспределения, который может сохранять сортировку. Он перераспределяет выборку по потокам таким образом, чтобы они потом могли эффективно сортироваться и агрегироваться.

  • Далее вызывается оператор параллелизма Gather – это самый распространенный оператор, который собирает данные.

  • И в дальнейшем происходит объединение двух группирующих наборов (оператор Concatenation) – результат выдается на клиентский контекст.

 

Топ запросов по Duration и CPU Time, где CPU Time >>> Duration

 

 

Как еще можно определить, что у нас все выполнялось параллельно?

Если мы посмотрим время работы ЦП, то при параллельном выполнении оно будет значительно больше, чем время, затраченное на выполнение запроса. Напомню, что в качестве времени ЦП здесь подсчитывается суммарное время процессов, которые были выполнены для конкретного оператора.

При использовании Extended Events подход такой же, как и с Profiler – мы можем собрать определенные метрики по Duration и CPU Time и определить, использовался ли параллелизм для конкретного запроса или нет.

По комбинации этих двух параметров можно сопоставить, во сколько раз CPU Time превышает Duration при включенном параллелизме и поиграть с параллелизмом.

Можно сделать грубо: поставить MaxDOP=1, собрать метрики и посмотреть, если Duration отличается незначительно, то профита от параллелизма нет.

 

Количество ожиданий CXPACKET

 

Как еще понять, есть ли у нас проблемы с параллелизмом? Можно проанализировать количество ожиданий CXPACKET. Статистику по этому ожиданию можно получить из представления DMV sys.dm_exec_requests – об этом рассказано в статье на Хабре.

 

 

Как это выглядит на примере? У меня есть база, где собрана статистика по ожиданиям. Здесь как раз можно увидеть данные кейса с чрезмерным параллелизмом, который я разбирал, когда пришел в компанию – как видите, количество ожиданий CXPACKET здесь в сотни раз больше, чем любых других ожиданий.

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

При условии, что и 1С, и СУБД крутятся на одном сервере, начинается определенная борьба за ресурс. Если используется Windows – он как-то сможет разрулить ситуацию, но если Linux – не знаю, насколько гибко это работает.

 

На что ориентироваться при настройке параллелизма для MS SQL

 

Количество ожиданий CXPACKET нужно уменьшать. Как это можно сделать?

  • На MS SQL можно выставить MaxDOP=1 (отключить параллелизм)

  • Или, если вы все-таки жаждете использовать параллелизм, поиграйтесь с параметром cost threshold for parallelism (настройка порога стоимости для параллелизма). Его можно завысить на максимальное значение (например, выставить 100) и постепенно уменьшать, наблюдая за статистикой – она накапливается с момента последнего перезапуска сервера (или службы).

Если количество ожиданий CXPACKET приближено к такому же значению при MaxDOP=1, то можно оставить текущие настройки параллелизма – при реструктуризации базы данных у вас будет включаться параллелизм, а на мелкие и средние запросы он включаться не будет. Это приведет к тому, что у вас будут свободные ядра для выполнения других задач.

 

Для включения плана запроса в PostgreSQL– модуль auto_explain

 

Для мониторинга того, есть ли профит от включения параллелизма в PostgreSQL, можно включать модули, которые идут в комплекте с ним. Например, auto_explain – онлайн-сбор логов. И pg_stat_statements.

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

 

Анализ параллелизма с помощью чтения плана запроса для PostgreSQL

 

 

Рассмотрим ситуацию с параллелизмом в PostgreSQL на базе 1С.

Мы выполним запрос для выборки с агрегацией, посмотрим, как это отражается в плане запроса – рассмотрим отличия плана запроса для PostgreSQL от MS SQL и посмотрим с помощью инструментов, есть ли профит от использования параллелизма.

Запрос выполняется достаточно долго, потому что в этом регистре сведений, напомню, 10 млн записей.

 

 

Анализировать план я буду в Notepad++ – я им всегда пользуюсь, читая планы запросы Postgres.

Конечно, есть специальные визуализаторы – например, хорошо себя зарекомендовал сервис https://explain.tensor.ru/ от СБИС (он же Тензор). Но в принципе, текстовая составляющая плана запроса для многих ясна – планы запросов читаются с конца на начало.

Какие моменты здесь говорят о параллелизме.

  • Здесь у нас полное параллельное сканирование таблицы Parallel Seq Scan. Ему выделено 4 воркера и 5 выполнений (loops = 5).

  • Здесь также есть нулевой поток, которые координирует данные, поступающие ему от параллельных процессов, следит, чтобы все собралось в узле Gather Merge – вы видите, что это сортируется в памяти и происходит сборка.

  • Мы видим количество запланированных воркеров на выполнение данного задания – Workers Planned;

  • И есть количество физически запущенных воркеров – Workers Launched.

  • И дальнейшее агрегирование – Finalize GroupAggregate.

Как можно понять, есть ли у нас проблемы при включении параллелизма на Postgres? Подход такой же, как на MS SQL – смотрим на суммарное время выполнения запроса Duration, отключаем параллелизм, выполняем запрос и снова смотрим Duration. Если значения почти не отличаются, то эффекта нет.

 

Выборка из представления pg_stat_statements, где total_time-blk_read_time < 0

 

 

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

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

 

Проблема временных таблиц в PostgreSQL

 

Хочу рассказать про момент, связанный с временными таблицами – это особенно касается типовых конфигураций – ERP, Бухгалтерия и т.д.

Если у вас на MS SQL был включен параллелизм, и запросы работали идеально, но как только перевели на Postgres – начались проблемы. Здесь могла выстрелить ключевая особенность – временные таблицы в PostgreSQL не включают параллелизм.

Типовые решения часто используют конструкции с помещением во временные таблицы. Особенно это касается блока ЗУП в ERP и конфигурацию «Бухгалтерия предприятия».

Если у вас запросы на MS SQL выполнялись за 3 секунды, а на Postgres обрабатывают 5 секунд, пользователи заметят разницу, и ничего хорошего не будет. По сути, у вас включен параллелизм на Postgres, вы хотите, чтобы все работало, как на MS SQL, но такого не будет, запросы будут выполняться медленнее.

 

Ложка дегтя

 

 

К чему еще может привести включенный параллелизм:

  • Чем больше пользователей работает при включенном параллелизме, тем больше ядер будет задействовано. Будет нехватка процессорного времени.

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

  • Если у вас неактуальная статистика, параллелизм может сразу «провалиться» – начать включаться там, где он не нужен. Неактуальная статистика ведет к неверной оценке, когда оптимизатор запросов будет пытаться распараллелить выполнение выборки, но профита от этого не будет.

  • Включение логирование в PostgreSQL – это как раз модуль auto_explain. Если включаем, будьте готовы, что логи вырастут.

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

  • В некоторых версиях платформы, более старых, и на более старых версиях СУБД возникали дедлоки при параллелизме – это описано в статье на ИТС. Слава Богу, сейчас такого нет, но об этом можно почитать. В этом случае нужно однозначно включать MaxDOP=1, и проблема уйдет.

 

Рекомендации

 

 

Если вы все-таки решили использовать параллелизм на MS SQL или на PostgreSQL, делайте это аккуратно.

  • Определенные сложные регламентные операции, у которых высокая оценка выполнения, мы делаем в технологическое окно, отведенное под операции 1С. Там у нас включается паралеллизм, и все прекрасно выполняется.

  • На проде мы завышаем значения cost threshold for parallelism в MS SQL – это тоже делается скриптом (так же, как включается MaxDOP), и у нас нет негативного эффекта от параллелизма. Да, некоторые запросы пробивает, но в целом наблюдается стабильное поведение системы.

  • Если используете PostgreSQL, то может быть вообще нет смысла трогать конфигурационный файл postgresql.conf в части асинхронного поведения. Потому что там достаточно мягкие настройки параллелизма и не все запросы будут пробиваться на параллелизм.

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

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

 

Использованные источники

 

 

Вопросы

 

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

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

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

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

А если мы включаем параллелизм на уровне СУБД – результат может быть непредсказуем. Потому что мы передаем на СУБД, то MS SQL – это черный ящик, мы не знаем, будет он включать параллелизм или нет. С PostgreSQL та же самая история.

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

Если вы все-таки включили параллелизм и надеетесь, что у вас все будет хорошо, вы должны быть уверены в том, что в вашей учетной системе хотя бы 90% запросов адекватные – что у вас все нормально со статистикой, что у вас хватает ядер, что ваши подрядчики написали запросы хорошо. Тогда во включении параллелизма есть смысл.

Почему может расти CXPACKET?

CXPACKET есть всегда, он всегда в топе. Даже если вы не используете параллелизм, у вас всегда есть ожидания, потому что чем больше пользователей, тем больше исполнителей для выполнения заданий запросов используется. И все они пытаются считать определенные страницы – ждут своей очереди выполнения. Как раз это ожидание и говорит о том, что есть исполнители, которые ждут своего часа выполнения. В случае с параллелизмом это значение просто выше ожидания. И опять же, там нужно смотреть в совокупности с другими типами ожиданий – например, с PAGEIOLATCH_XX, с ожиданием на чтение страниц.

Анализировали ли вы влияние параллелизма на множественные вставки в таблицы с большим количеством данных – дает ли параллелизм какой-то профит при этом или нет?

При вставке в таблицы никакого параллелизма не используется. Единственный момент, когда он может использоваться помимо оператора SELECT – при CREATE INDEX – там включается параллелизм, и он хорошо работает на той же реструктуризации, реиндексации. В случае INSERT, DELETE, UPDATE у вас параллелизм не включается. Параллелизм гарантированно сработает, если вы делаете SELECT с агрегацией данных, при этом на PostgreSQL, если вы помещаете данные во временные таблицы, параллелизм работать не будет. Никакие другие операции с СУБД кроме SELECT отношения к параллелизму не имеют.

 

*************

Данная статья написана по итогам доклада (видео), прочитанного на онлайн-митапе "PostgreSQL VS Microsoft SQL"

Вступайте в нашу телеграмм-группу Инфостарт

См. также

HighLoad оптимизация Программист 1С 8.3 1С:ERP Управление предприятием 2 Бесплатно (free)

Использование оператора «В» для полей или данных составного типа (например, Регистратор) может приводить к неочевидным проблемам.

10.11.2025    5849    ivanov660    48    

51

HighLoad оптимизация Программист 1С:Предприятие 8 1C:ERP Бесплатно (free)

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

18.02.2025    8484    ivanov660    39    

61

HighLoad оптимизация Технологический журнал Системный администратор Программист Бесплатно (free)

Обсудим поиск и разбор причин длительных серверных вызовов CALL, SCALL.

24.06.2024    10876    ivanov660    13    

64

HighLoad оптимизация Программист 1С:Предприятие 8 Бесплатно (free)

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

06.06.2024    16958    Evg-Lylyk    73    

46

HighLoad оптимизация Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

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

13.03.2024    8342    spyke    29    

54

HighLoad оптимизация Программист 1С:Предприятие 8 Бесплатно (free)

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

13.03.2024    11694    vasilev2015    22    

47
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Yashazz 4891 13.08.21 12:50 Сейчас в теме
Еще хороший подход, если вы организуете параллелизм на уровне учетной системы.
Можно подробнее? Есть возможность связать настройки скуля с типом сеанса/соединения 1С?
2. Shmell 616 13.08.21 14:06 Сейчас в теме
(1) Все достаточно тривиально - механизм фоновых заданий. Например, у вас в выборке 1000 элементов. Разбейте выборку на 2 порции по 500 и распараллельте через запуск 2х фоновых заданий. Потом соберите результат, если нужно в точке ожидания. Принцип, отдалено похожий на map reduce.
1CUnlimited; Yashazz; gubanoff; +3 1 Ответить
3. RustIG 1934 17.08.21 09:04 Сейчас в теме
(2) тривиально, это когда запрос по просрочкам надо тащить для 10 млн. записей? а потом из этого доклад делать?

пример укажите достойный , раз поднимаете проблематику.
8. 1CUnlimited 417 07.10.22 17:01 Сейчас в теме
(1)
(2)
Это по сути горизонтальное маштабирование вычислений, мы на нем серьезные объемы обрабатываем , но 1С к сожалению и для него имеет четкие ограничения платформы см тут https://infostart.ru/1c/articles/1683197/
Но у Вас как понимаю из цитата и 1С и MS SQL на одном сервере
"
При условии, что и 1С, и СУБД крутятся на одном сервере, начинается определенная борьба за ресурс. Если используется Windows – он как-то
сможет разрулить ситуацию, но если Linux – не знаю, насколько гибко это работает.
"
а это уже искажает картину
MS SQL подддерживает правильную работу c Numa node а 1С о них не знает и полагается на ОС. Это легко может привести к тому что процессы 1С и MS SQL пересекутся по ядрам и узкие места могут появлятся в любых местах
поэтому если уж играться с параллелизмом на уровне запросов то строго на выделенном сервере для СУБД , так он хотябы правильно отработает по Numa node
4. starik-2005 3207 17.08.21 16:53 Сейчас в теме
Cost = M * N * Log(N)

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

А количество работников в этой формуле - это N или M? В любом случае, формула показывает линейный рост cost от количества работников.

ЗЫ: некоторые из читающих знают арифметику (я, например, хоть у меня и три класса церковно-приходской).
7. alalsl 13 26.08.21 16:49 Сейчас в теме
(4) M.
Работники же мешают друг-другу)
5. Yashazz 4891 18.08.21 08:27 Сейчас в теме
Чтобы быть более-менее уверенным, что у нас выполнится и будет с этого какой-то профит, лучше по возможности применять алгоритмы обработки в учетной системе. Это топорно, но чем проще, тем лучше.

Если вы все-таки включили параллелизм и надеетесь, что у вас все будет хорошо, вы должны быть уверены в том, что в вашей учетной системе хотя бы 90% запросов адекватные – что у вас все нормально со статистикой, что у вас хватает ядер, что ваши подрядчики написали запросы хорошо. Тогда во включении параллелизма есть смысл.

Что из этой публикации можно почерпнуть?
1. Нормально пишите алгоритмы и запросы самой 1С. Замечательный совет)
2. Параллелизм и прочие жуткие ужасы СУБД лучше не трогать, а если трогать, то как 1С сказала, т.е. ставить 1 и отойти в сторонку, иначе хз что будет. Тоже прям открытие века)

Вывод? Полезность очень так себе. Ни о чём статья. Хороша только упоминанием моментов, которые при расследовании узких мест могут пригодиться. И всё...
rovenko.n; +1 2 Ответить
6. Redokov 82 20.08.21 12:31 Сейчас в теме
(5)
1. Нормально пишите алгоритмы и запросы самой 1С

Уже неплохо. А так еще немного теории описано и про собственные шишки рассказано. Нормальная статья. Полезная.
SergeiGer; user997914; RedAllert; Lacoste4life; user1203996; Shmell; +6 Ответить
9. RedAllert 23.01.24 13:29 Сейчас в теме
Я от греха отключил его хотя ресурсов у меня хватает с головой и ни скуль, ни система их выбрать не в состоянии.
Основная боязнь не в том, что он сожрет все ресурсы сервера, а в том что легко можно получить ситуацию, когда при одновременной работе нескольких пользователей системы с одним объектом изменения не сохранятся или сохранятся не те.

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

Поправьте меня, если я не прав.
Для отправки сообщения требуется регистрация/авторизация