이번 포스팅에서는 Greenplum DB에서 PL/R을 실행했을 때 "Error on receive from seg0 slice1: server closed the connection unexpectedly" 에러가 발생했을 경우 확인해보고 수정하는 예를 소개하겠습니다. 


먼저, PL/R의 input으로 사용할 array 가 들어있는 간단한 예제 테이블을 만들어보겠습니다. 



create schema test;


drop table if exists test.sample_tbl_agg;

create table test.sample_tbl_agg (

grp varchar(50) not null

, prod varchar(50)

, x_agg integer[]

, y_agg numeric[]

) distributed by (grp, prod);


insert into test.sample_tbl_agg values ('AA', 'GGG', array[1, 2, 3, 4, 5], array[0.112, 0.243, 0.318, 0.416, 0.534]);

insert into test.sample_tbl_agg values ('BB', 'SSS', array[1, 2, 3, 4, 5], array[0.103, 0.212, 0.302, 0.453, 0.593]);


select * from test.sample_tbl_agg;





 (1) Greenplum DB에서 PL/R return 받는 데이터 유형을 잘못 설정할 경우 

     server closed the connection unexpectedly 에러 발생


예제로 사용한 PL/R 함수는 국소 회귀모형(Local Regression)R의 LOESS() 함수를 적합해서 평활(smoothing)한 결과값을 array형태로 반환하는 것입니다. 그런데 returns numeric[] 으로 하는 바람에 서버가 비정상적으로 끊기고 리커버리 되는 상황이 발생하였습니다. 



------------------------------------------

-- PL/R on Greenplum : Error

--Query execution failed

--

--Reason:

--SQL Error [58M01]: ERROR: Error on receive from seg0 slice1 172.17.0.2:40000 pid=895: server closed the connection unexpectedly

--  Detail: 

-- This probably means the server terminated abnormally

-- before or while processing the request.

------------------------------------------


drop function if exists test.exec_loess(integer[], numeric[]);

create or replace function test.exec_loess(x integer[], y numeric[]) 

returns numeric[] -- **** it causes an error ****

as 

$$

y_loess <- loess(y~ x)$fitted 

return (y_loess)

$$ language plr;


-- Execute PL/R LOESS, but Error (server closed -_-;;;)

select 

grp

, prod

, x_agg

, test.exec_loess(x_agg, y_agg) as y_loess -- error

from test.sample_tbl_agg;





  (2) PL/R return 데이터 유형을 맞게 설정해줄 경우 정상 수행됨


이번에는 위의 (1)번에서 정의했던 PL/R 함수를 삭제(drop)하고 y 에 해당하는 인자의 데이터 유형을 기존numeric[] 에서 float8[] 으로 새로 변경하고, return 받는 데이터 유형도 기존의  returns numeric[] 에서 returns float8[] 로 변경하여 정의한 후에 PL/R 함수를 실행해보겠습니다. PL/R이 Greenplum에서 정상적으로 잘 수행되네요. 


PL/R 수행 후의 결과를 return 받을 데이터 유형 (data type)을 잘 확인하고 맞게 설정을 해주어야 합니다. 



-- drop old PL/R UDF which used 'returns numeric[]'

drop function if exists test.exec_loess(integer[], numeric[]); 


-- create new PL/R UDF which uses 'returns float[]'

drop function if exists test.exec_loess(integer[], float8[]);

create or replace function test.exec_loess(x integer[], y float8[]) 

returns float8[] -- ** not numeric[], but float8[] **

as 

$$

y_loess <- loess(y~ x)$fitted 

return (y_loess)

$$ language plr;



-- Execute PL/R LOESS

select 

grp

, prod

, x_agg

, test.exec_loess(x_agg, y_agg) as y_loess_agg

from test.sample_tbl_agg;





본 포스팅의 주제는 아닙니다만, 위의 PL/R에서 반환받는 값이 array 형태이다보니 조회해서 보기에, 또 이를 가지고 연산을 하거나 다른 테이블과 조인을 하기에 불편한감이 있습니다. 이에 unnest() 함수를 사용해서 array를 풀어서 long format으로 조회하는 예제도 추가로 아래에 예를 들어보았습니다. 



-- unnest to see in a long format

select 

a.grp

, a.prod

, unnest(a.x_agg) as x

, unnest(a.y_loess_agg) as y_loess

from (

select 

grp

, prod

, x_agg

, test.exec_loess(x_agg, y_agg) as y_loess_agg

from test.sample_tbl_agg) a;






  (3) returns setof 을 사용해서 행(row) 단위로 PL/R 결과를 반환하기

      (returns rows instead of array using 'returns setof' in PL/R on Greenplum)


위의 (2)번에서 unnest() 를 소개한 김에 옆으로 조금만 더 세어보자면요, 

위의 (2)번에서는 returns float8[]        --> PL/R 수행 시 array 를 반환했던 반면에, 

이번 (3)번에서는 returns setof float8   --> PL/R 수행 시 rows 를 반환하도록 하는 경우입니다. 


'returns setof' 처럼 'setof'가 추가된게 다르구요, 'float8[]' array가 아니라 'float8' 형태인게 다릅니다. 

이렇게 개별 float8 값을 row로 반환하므로 위의 (2)번처럼 unnest() 함수를 써서 array를 long format으로 풀어줄 필요가 없이도 (2)번의 unnest() 를 쓴 것과 동일한 결과를 얻었습니다.  



---------------------------------------

-- returns setof: rows in a long format

---------------------------------------

drop function if exists test.exec_loess(integer[], float8[]);

create or replace function test.exec_loess(x integer[], y float8[]) 

returns setof float8 -- not array, but rows

as 

$$

y_loess <- loess(y~ x)$fitted 

return (y_loess)

$$ language plr;



-- Execute PL/R LOESS

select 

grp

, prod

, unnest(x_agg) as x

, test.exec_loess(x_agg, y_agg) as y_loess -- not array, but rows

from test.sample_tbl_agg;

 




많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. 



Posted by R Friend R_Friend

댓글을 달아 주세요