Адекватный параллелизм в 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 оптимизация Технологический журнал Системный администратор Программист Бесплатно (free)

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

24.06.2024    5169    ivanov660    12    

56

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

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

06.06.2024    9290    Evg-Lylyk    61    

44

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

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

13.03.2024    5114    spyke    28    

49

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

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

13.03.2024    7597    vasilev2015    20    

42

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

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

2 стартмани

15.02.2024    12463    241    ZAOSTG    82    

115

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

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

1 стартмани

24.01.2024    5689    glassman    18    

40

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

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

09.01.2024    14104    doom2good    49    

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

пример укажите достойный , раз поднимаете проблематику.
8. 1CUnlimited 320 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 3088 17.08.21 16:53 Сейчас в теме
Cost = M * N * Log(N)

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

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

ЗЫ: некоторые из читающих знают арифметику (я, например, хоть у меня и три класса церковно-приходской).
7. alalsl 11 26.08.21 16:49 Сейчас в теме
(4) M.
Работники же мешают друг-другу)
5. Yashazz 4791 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С

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

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

Поправьте меня, если я не прав.
Оставьте свое сообщение