PostgreSQL: падение производительности при использовании нескольких функций без аппаратного узкого места - PullRequest
0 голосов
/ 21 января 2020

У меня есть простая функция, если я ее запускаю, это займет около 40 секунд до конца sh.

select * from f_cyklus1(100000000) 

, но если я запускаю эту функцию 8 раз в 8 отдельных экземплярах, то есть все 8 функций выполняются параллельно, это занимает от 210 до 260 секунд до окончания sh для каждого из ее экземпляров. Что является значительным падением производительности. Я попытался скомпилировать его как 8 отдельных функций и запустить его снова, но производительность не изменилась.

select * from f_cyklus1(100000000); 
select * from f_cyklus2(100000000); 
select * from f_cyklus3(100000000); 
select * from f_cyklus4(100000000); 
select * from f_cyklus5(100000000); 
select * from f_cyklus6(100000000); 
select * from f_cyklus7(100000000); 
select * from f_cyklus8(100000000); 

Так почему же требуется 40 секунд по сравнению с 210-260 с окончанием sh? Наша виртуальная машина имеет 16 процессоров, и физическое оборудование использовалось с низкой нагрузкой. Я также был единственным, кто использовал базу данных Postgre во время тестирования.

create or replace function f_cyklus1 (p_rozsah int) returns bigint as -- drop function f_cyklus(int)
$body$
declare 

declare 
  v_exc_context        TEXT;
  v_result             INTEGER;

  p_soucet bigint :=0;
begin

for i in 0..p_rozsah
loop
p_soucet = p_soucet + i;
end loop;

return p_soucet;

EXCEPTION
  WHEN OTHERS THEN
    GET STACKED DIAGNOSTICS v_exc_context = PG_EXCEPTION_CONTEXT;
    PERFORM main.ut_log('ERR', SQLERRM || ' [SQL State: ' || SQLSTATE || '] Context: ' || v_exc_context );
    RAISE;
END;
$body$ LANGUAGE plpgsql

PostgreSQL 11.6 на x86_64-p c - linux -gnu, скомпилированный g cc (G CC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-разрядная

Виртуальная машина: Centos 7 + KVM

HW: 2x драм EPY C 7351 + 256 ГБ ОЗУ

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

1 Ответ

1 голос
/ 22 января 2020
p_soucet = p_soucet + i;

Каждый раз, когда вы делаете это, он должен получить «моментальный снимок» для запуска оператора, поскольку он использует обычный механизм SQL за кулисами, который всегда должен запустить в снимке. Для получения снимка требуется общесистемная блокировка. Чем больше процессов вы выполняете одновременно, тем больше времени они тратят на борьбу за получение снимка, а не на выполнение полезной работы.

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

plpg sql не очень хорошо подходит для такого рода работ, за исключением масштабирования. Вы можете использовать один из других языков pl, например pl perl или plpythonu.

Как выражения оцениваются основным SQL движком, описано в https://www.postgresql.org/docs/current/plpgsql-expressions.html

Снимки обсуждаются в основном в документах, начиная с https://www.postgresql.org/docs/current/mvcc.html

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...