2023년 5월 16일 화요일

GP2GP (Greenplum 클러스터간 연동, Greenplum_fdw)



Greenplum 6.20+에서는 클러스터간의 쿼리 실행할 수 있도록 Foreign data wrapper(FDW)를 제공합니다.

Greenplum FDW
 - Greenplum 클러스터간의 쿼리 실행할 수 있는 Foreign data wrapper(외부 데이터 래퍼)
 - Local Greenplum에서 Remote Greenplum 의 인스턴스 차이가 나더라도 병렬처리 지원
 - 외부 테이블에 대해서 조회 기능 제공
 - pushdown 기능 제공: 원격지의 테이블을 조회할 경우, index/파티션 수행후 결과 리턴 
   => 리모트의 테이블 전체를 가져오는 것이 아니라, 필요한 부분만 필터링해서 가져옴. 





1. 테스트 환경 

1.1 Remote

 - OS: CentOS Linux release 7.9

 - Greenplum: 6.21.0

 - 4 segment VM

 - 4 Primary segment instance 


1.2 Local

 - OS: Rocky Linux release 8.7 

 - Greenplum: 6.23.0

 - 1 segment VM

 - 2 Primary segment instance


2. 사전 준비

2.1 remote 서버

 -  Local 서버의 mdw/smdw/vip IP 등록

[gpadmin@mdw ~]$ vi $MASTER_DATA_DIRECTORY/pg_hba.conf

host    all          all             172.16.65.90/32        md5


2.2 local 서버

 - local 서버에서 remote 서버로 접속하기 때문에, local 서버에서 remote 서버 접속이 가능해야 함.

 - local 서버에서 remote 서버로 접속할 때에는 remote 서버의 hostname을 참고 함. 

 - gp_segment_configuration의 hostname 찾음.

 - local 서버에 /etc/hosts에 remote 서버 리스트가 포함 되어야 함.

 - ex) 


[gpadmin@r8g6single ~]$ cat /etc/hosts

# local server

172.16.65.90 r8g6single


# remote server 리스트 추가

172.16.65.141 c7g6mdw

172.16.65.141 c7g6sdw1

172.16.65.142 c7g6sdw2

172.16.65.143 c7g6sdw3

172.16.65.144 c7g6sdw4 



3. Greenplum_pdw 셋업

3.1 Remote

CREATE EXTENSION IF NOT EXISTS gp_parallel_retrieve_cursor;



3.2 Local

CREATE EXTENSION greenplum_fdw;

CREATE EXTENSION IF NOT EXISTS gp_parallel_retrieve_cursor;


--Options 옆에 -- 와 같은 주석 처리하면 안됨.

--클러스터간의 병렬 연동을 위해서는 2가지 옵션을 적용해야 함.

1) mpp_execute 'all segments' --병렬로 처리하기 위한 옵션

2) num_segments '4'  --원격지의 세그먼트 개수, default 값은 원격지 세그먼트 인스턴스 수,


CREATE SERVER gp_remote_edu

       FOREIGN DATA WRAPPER greenplum_fdw 

       OPTIONS (host '172.16.65.140',            

                port '5432',      

                dbname 'edu',                     

                mpp_execute 'all segments', 

                num_segments '4');


CREATE USER MAPPING FOR udba 

       SERVER gp_remote_edu 

       OPTIONS (user 'udba', password 'changeme');


CREATE USER MAPPING FOR gpadmin 

       SERVER gp_remote_edu 

       OPTIONS (user 'gpadmin', password 'changeme');


DROP FOREIGN TABLE remote.lineitem;

CREATE FOREIGN TABLE remote.lineitem (

    l_orderkey bigint NOT NULL,

    l_partkey integer NOT NULL,

    l_suppkey integer NOT NULL,

    l_linenumber integer NOT NULL,

    l_quantity numeric(15,2) NOT NULL,

    l_extendedprice numeric(15,2) NOT NULL,

    l_discount numeric(15,2) NOT NULL,

    l_tax numeric(15,2) NOT NULL,

    l_returnflag character(1) NOT NULL,

    l_linestatus character(1) NOT NULL,

    l_shipdate date NOT NULL,

    l_commitdate date NOT NULL,

    l_receiptdate date NOT NULL,

    l_shipinstruct character(25) NOT NULL,

    l_shipmode character(10) NOT NULL,

    l_comment character varying(44) NOT NULL

)

SERVER gp_remote_edu 

OPTIONS (schema_name 'edu_sch', table_name 'lineitem'); 


--test

select * from remote.lineitem limit 10;



4. 쿼리 테스트

4.1 remote 서버에서 internal table 쿼리 수행 (4vm, 4 primary segment)

edu=# select count(*) from edu_sch.lineitem where l_shipdate >= '19990101' and l_shipdate <'19990131';

 count

-------

  8894

(1 row)


Time: 103.797 ms

edu=#


4.2 local서버에서 remote 테이블에 쿼리 수행

- remote : 4 segment vms, 4 primary instances

- local  : 1 segment vms, 2 primary instances

## pushdown 기능제공,리모트  테이블에서는 파티션이 포함되어 있음.

gpadmin=# select count(*) from remote.lineitem where l_shipdate >= '19990101' and l_shipdate <'19990131';

 count

-------

  8894

(1 row)


Time: 350.271 ms

gpadmin=#


5. 규모 있는 장비에서 테스트한 결과

5.1 테스트 환경 

- Greenplum #1 : Master: 2VMs, Segment:   4VMs, 8 primay instance/VM, total primary:    32

- Greenplum #2 : Master: 2VMs, Segment: 3~4VMs, 8 primay instance/VM, total primary: 24~32


5.1 테스트 테이블

 - LOG 테이블   : 압축6.6GB, 비압축  12GB, 데이터 직렬화(array data)

 - MASTER 테이블: 압축 42MB, 비압축 294MB, row model 데이터

                        수행시간(초)     







2021년 12월 14일 화요일

Greenplum에서 hierarchy, Path와 같이 Recursive 쿼리

 Greenplum에서 hierarchy, Path와 같이 Recursive 쿼리 샘플입니다.


1. 쿼리 패턴 

1) with recursive 쿼리 
   - 메뉴와 조직과 같이 UI 에서 사용하며 테이블의 사이즈가 작을 경우 권고
   - 쿼리상의 root 변경시 편리 함.


2) self left outer join
   - 웹로그, 센서로그와 같이 대용량의 데이터의 path 분석시 권고
   - 대용량 처리시에 left outer join의 성능이 recursive 쿼리 보다 훨씬 좋기 때문

2. 쿼리 샘플   


create table public.places

(

   place text

   is_in text

)

distributed by (place);


insert into public.places 

values 

  ('한국', null)

, ('서울', '한국')

, ('강남구', '서울')

, ('삼성동', '강남구')

, ('경기', '한국')

, ('의왕', '경기')

, ('내손동', '의왕')

, ('양산', '한국')

, ('삼성동', '양산')

, ('미국', null)

, ('캘리포니아','미국')

, ('샌프란시스코','캘리포니아')

, ('플로리다','미국')

, ('마이에미','플로리다')

;



with recursive q (place, is_in, depth)

as

(

select place, is_in, 1 

from   places

where  is_in is null

union all

select m.place, m.is_in, q.depth + 1

from   places m

join   q on q.place = m.is_in

)

selectfrom q;

    place     |   is_in    | depth 

--------------+------------+-------

 한국         |            |     1

 양산         | 한국       |     2

 경기         | 한국       |     2

 서울         | 한국       |     2

 삼성동       | 양산       |     3

 의왕         | 경기       |     3

 강남구       | 서울       |     3

 내손동       | 의왕       |     4

 삼성동       | 강남구     |     4

 미국         |            |     1

 캘리포니아   | 미국       |     2

 플로리다     | 미국       |     2

 샌프란시스코 | 캘리포니아 |     3

 마이에미     | 플로리다   |     3

 

with recursive

(place, is_in, depth, path, cycle)

as

(

select place, is_in, 1 as depth, array[place], false as cycle from places

where is_in is null

union all

select m.place, m.is_in

      , q.depth + 1 as depth

      , path || m.place, m.place = any(path) from  places m

join q on q.place = m.is_in

where not cycle

)

select place, is_in, depth, array_to_string(path, '>'), cycle from q;


    place     |   is_in    | depth |       array_to_string        | cycle

--------------+------------+-------+------------------------------+-------

 미국         |            |     1 | 미국                         | f

 플로리다     | 미국       |     2 | 미국>플로리다                | f

 캘리포니아   | 미국       |     2 | 미국>캘리포니아              | f

 마이에미     | 플로리다   |     3 | 미국>플로리다>마이에미       | f

 샌프란시스코 | 캘리포니아 |     3 | 미국>캘리포니아>샌프란시스코 | f

 한국         |            |     1 | 한국                         | f

 양산         | 한국       |     2 | 한국>양산                    | f

 서울         | 한국       |     2 | 한국>서울                    | f

 경기         | 한국       |     2 | 한국>경기                    | f

 삼성동       | 양산       |     3 | 한국>양산>삼성동             | f

 강남구       | 서울       |     3 | 한국>서울>강남구             | f

 의왕         | 경기       |     3 | 한국>경기>의왕               | f

 삼성동       | 강남구     |     4 | 한국>서울>강남구>삼성동      | f

 내손동       | 의왕       |     4 | 한국>경기>의왕>내손동        | f

(14 rows)



select path_str, path_arr, depth

     , path_arr[1] d1

     , path_arr[2] d2

     , path_arr[3] d3

     , path_arr[4] d4

from   (

select  array_to_string(path_arr, '>') path_str

            ,   string_to_array(array_to_string(path_arr, '>'), '>') path_arr

    ,   array_length(string_to_array(array_to_string(path_arr, '>'), '>'), 1) depth

from (

select  array[e.place, d.place, c.place, b.place, a.place] path_arr            

from   places a

left outer join places b 

on     a.is_in = b.place

left outer join places c 

on     b.is_in = c.place

left outer join places d 

on     c.is_in = d.place

left outer join places e 

on     d.is_in = e.place

) a1 

) a2

--where path_arr[1] = '한국'

order by 2

;


           path_str           |            path_arr            | depth |  d1  |     d2     |      d3      |   d4

------------------------------+--------------------------------+-------+------+------------+--------------+--------

 미국                         | {미국}                         |     1 | 미국 |            |              |

 미국>플로리다                | {미국,플로리다}                |     2 | 미국 | 플로리다   |              |

 미국>플로리다>마이에미       | {미국,플로리다,마이에미}       |     3 | 미국 | 플로리다   | 마이에미     |

 미국>캘리포니아              | {미국,캘리포니아}              |     2 | 미국 | 캘리포니아 |              |

 미국>캘리포니아>샌프란시스코 | {미국,캘리포니아,샌프란시스코} |     3 | 미국 | 캘리포니아 | 샌프란시스코 |

 한국                         | {한국}                         |     1 | 한국 |            |              |

 한국>경기                    | {한국,경기}                    |     2 | 한국 | 경기       |              |

 한국>경기>의왕               | {한국,경기,의왕}               |     3 | 한국 | 경기       | 의왕         |

 한국>경기>의왕>내손동        | {한국,경기,의왕,내손동}        |     4 | 한국 | 경기       | 의왕         | 내손동

 한국>서울                    | {한국,서울}                    |     2 | 한국 | 서울       |              |

 한국>서울>강남구             | {한국,서울,강남구}             |     3 | 한국 | 서울       | 강남구       |

 한국>서울>강남구>삼성동      | {한국,서울,강남구,삼성동}      |     4 | 한국 | 서울       | 강남구       | 삼성동

 한국>양산                    | {한국,양산}                    |     2 | 한국 | 양산       |              |

 한국>양산>삼성동             | {한국,양산,삼성동}             |     3 | 한국 | 양산       | 삼성동       |

(14 rows)

Greenplum Ghost Index

Greenplum 7.6+에서 Ghost Index (Implied index)를 지원합니다. 1. Ghost Index 개념    - 컬럼 압축테이블(AO/CO)에 blockdirectory 옵션을 적용하여,        인덱스가 없더라도 Block...