#postgresql #plpython #plperl
#postgresql #plpython #plperl
Вопрос:
Мы фактически переносим БД с oracle на postgres. Мы используем PostgreSQL 11. Таким образом, пакеты соответствующим образом преобразуются в процедуры / функции.
Для реализации глобальных переменных мы использовали настройки локальной конфигурации, как показано ниже
SET pkg.variable = value;
select current_setting('pkg.variable');
Однако эти значения становятся пустыми, если они попадают в блок исключений, и нам нужно, чтобы значение было доступно в блоке исключений, чтобы выполнить какую-то другую логику при сбое.
Итак, мы выбрали подход использования глобальных переменных с использованием расширения plperl / plpython, как показано ниже,
CREATE OR REPLACE FUNCTION set_var(name text, val text)
RETURNS void
LANGUAGE 'plperl'
AS $BODY$
undef $_SHARED{$_[0]};
$_SHARED{$_[0]} = $_[1];
$BODY$;
CREATE OR REPLACE FUNCTION get_var(name text)
RETURNS text
LANGUAGE 'plperl'
AS $BODY$
return $_SHARED{$_[0]};
$BODY$;
plpython, как показано ниже
CREATE OR REPLACE FUNCTION set_var(var text, val text)
RETURNS void
LANGUAGE plpythonu
AS $function$
if var not in GD:
GD[var] = val
else:
del GD[var]
GD[var] = val
$function$ ;
CREATE OR REPLACE FUNCTION get_var(var text)
RETURNS text
LANGUAGE plpythonu
AS $function$
if var in GD:
return GD[var]
else:
return None
$function$
Мы устанавливаем значение и извлекаем значение следующим образом,
PERFORM set_var('pkg.variable',value) -- to set the variable
select get_var('pkg.variable') --to get the value.
Вызываемая нами процедура имеет цикл for внутри и inreturn вызывает множество других процедур, которые установят в общей сложности около 270 таких глобальных переменных для каждого цикла. Значение глобальных переменных будет обновляться до нового значения для тех же 270 переменных, которые мы уже создали в первом цикле. Это должно произойти примерно для 300 000 строк в цикле for.
Однако при такой реализации потребление памяти становится очень высоким, и в какой-то момент оно достигает состояния нехватки памяти и останавливается примерно на 157000-й строке.
Я не очень разбираюсь в perl или python, но, основываясь на том, что я понял из Интернета, я добавил undef() и del для perl и python соответственно, что освободило бы память. Однако этого не происходит.
Мы также взяли адрес переменной set, чтобы посмотреть, обновляется ли он по тому же адресу или принимает новый адрес памяти при каждом вызове. Он обновляет значение по тому же адресу, по которому была создана переменная.
Но память продолжает накапливаться сверхурочно, пока не использует всю доступную оперативную память и выдает ошибку как из памяти.
Если кто-нибудь может помочь мне понять, что я сделал неправильно или что я могу изменить, чтобы заставить его работать нормально, это было бы очень полезно. Заранее спасибо.
ОБНОВЛЕНИЕ: проблема была связана с использованием процедур. Мы изменили код на функции, и проблемы с потреблением памяти нет. Мне еще предстоит выяснить, почему существует такая огромная разница в использовании процедур и функций.
Комментарии:
1. Сколько материала вы храните в этой
$_SHARED
переменной?2. Это количество элементов, в которых мы храним,
$_SHARED
я думаю, это будет 270 переменных со значениями этого .. и мы должны обновлять одну и ту же переменную с новым значением для каждого цикла.3. Значения очень большие? В любом случае, как насчет того, чтобы обойтись без таких переменных и передать состояние функциям в виде параметров? Глобальные переменные в любом случае часто являются плохим принципом проектирования.
4. Значения невелики.. Я не понял, передавая его как состояние для функции..
5. Поддерживайте «глобальные переменные» на стороне клиента и передавайте их функциям, когда это необходимо.