2025년 1월 19일 일요일

Greenplum 6에서 Table SKEW 확인 방법

Greenplum 6에서 Table SKEW 확인 방법

소스

https://github.com/gpdbkr/gpkrutil/blob/main/mngdb/chk_table_skew.sql

- https://knowledge.broadcom.com/external/article?articleNumber=295161

- https://knowledge.broadcom.com/external/article?articleNumber=295215



1. 히든 컬럼(gp_segment_id )을 이용한 방법

   - 테이블의 세그먼트 인스턴스별로 row수를 확인

   - 장점: 매우 직관적, 쉽게 확인 가능

   - 단점: 테이블별/파티션별로 수행 필요, 수행시점에 Table Full 스캔

   - 예시 


SELECT gp_segment_id, COUNT(*)

FROM <schema_name>.<table_name>

GROUP BY gp_segment_id

ORDER BY 1;


2. Greenplum의 운영을 위한 view로 확인 

   - view 조회 시점, 내부적으로 gp_segment_id를 수행하여 결과를 보여 줌

   - 관련 view: gp_toolkit.gp_skew_coefficients, gp_toolkit.gp_skew_idle_fractions

   - 장점: DB내의 모든 테이블의 SKEW를 확인 가능 

   - 단점: 부하가 많고, 시간이 많이 걸림(view 조회 시점에 full 스캔을 하기에 실 운영환경에서는 비권고)

   - 예시 

SELECT * 

FROM gp_toolkit.gp_skew_coefficients;

SELECT * 

FROM gp_toolkit.gp_skew_idle_fractions;


3. 모든 세그먼트에서 테이블의 OS 파일 사이즈로 확인 방법

   - 모든 세그먼트의 OS 파일을 external table로 만든 다음 사이즈 체크 

   - 장점: 전체 DB 확인시 매우 빠름 

   - 단점: DML 발생시에는 해당 테이블 반영안될수 있음. 함수 생성 필요 

   - 예시


1)  함수 생성 - Greenplum 6


DROP FUNCTION IF EXISTS public.greenplum_check_skew();

CREATE FUNCTION public.greenplum_check_skew()

    RETURNS TABLE (

    relation text,

    vtotal_size_gb numeric,

    vseg_min_size_gb numeric,

    vseg_max_size_gb numeric,

    vseg_avg_size_gb numeric,

    vseg_gap_min_max_percent numeric,

    vseg_gap_min_max_gb numeric,

    vnb_empty_seg bigint)

    LANGUAGE plpgsql

    AS $$

DECLARE

v_function_name text := 'greenplum_check_skew';

    v_location int;

    v_sql text;

    v_db_oid text;

BEGIN

 /* 

The function checks the skew on greenplum table via OS file size

* The table "greenplum_get_refilenodes" collects all the relfilenodes found on the database from all segments

* The external "greenplum_get_db_file_ext" tables collects all the files that are on the base directory

* The view "greenplum_get_file_statistics" combines the relfilenodes and displays the size of the relation by segments

* The view "greenplum_get_skew_report" provide high level overview of the skew

*/

    -- Set the client min messages to just warning

    v_location := 1000;

    SET client_min_messages TO WARNING;


    -- Get the database oid

    v_location := 2000;

    SELECT d.oid INTO v_db_oid

    FROM pg_database d

    WHERE datname = current_database();


    -- Drop the temp table if it exists

    v_location := 3000;

    v_sql := 'DROP TABLE IF EXISTS public.greenplum_get_refilenodes CASCADE';

    v_location := 3100;

    EXECUTE v_sql;


    -- Temp table to temporary store the relfile records

    v_location := 4000;

    v_sql := 'CREATE TABLE public.greenplum_get_refilenodes ('

    '    segment_id int,'

    '    o oid,'

    '    relname name,'

    '    relnamespace oid,'

    '    relkind char,'

    '    relfilenode bigint'

    ')';

    v_location := 4100;

    EXECUTE v_sql;


    -- Store all the data related to the relfilenodes from all

    -- the segments into the temp table

    v_location := 5000;

    v_sql := 'INSERT INTO public.greenplum_get_refilenodes SELECT '

'  s.gp_segment_id segment_id, '

'  s.oid o, '

'  s.relname, '

'  s.relnamespace,'

'  s.relkind,'

'  s.relfilenode '

'FROM '

'  gp_dist_random(''pg_class'') s ' -- all segment

'UNION '

'  SELECT '

'  m.gp_segment_id segment_id, '

'  m.oid o, '

'  m.relname, '

'  m.relnamespace,'

'  m.relkind,'

'  m.relfilenode '

'FROM '

'  pg_class m ';  -- relfiles from master

v_location := 5100;

    EXECUTE v_sql;


-- Drop the external table if it exists

    v_location := 6000;

    v_sql := 'DROP EXTERNAL WEB TABLE IF EXISTS public.greenplum_get_db_file_ext';

    v_location := 6100;

    EXECUTE v_sql;


-- Create a external that runs a shell script to extract all the files 

-- on the base directory

v_location := 7000;

    v_sql := 'CREATE EXTERNAL WEB TABLE public.greenplum_get_db_file_ext ' ||

            '(segment_id int, relfilenode text, filename text, ' ||

            'size numeric) ' ||

            'execute E''ls -l $GP_SEG_DATADIR/base/' || v_db_oid ||

            ' | ' ||

            'grep gpadmin | ' ||

            E'awk {''''print ENVIRON["GP_SEGMENT_ID"] "\\t" $9 "\\t" ' ||

            'ENVIRON["GP_SEG_DATADIR"] "/base/' || v_db_oid ||

            E'/" $9 "\\t" $5''''}'' on all ' || 'format ''text''';


    v_location := 7100;

    EXECUTE v_sql;



    -- Drop the datafile statistics view if exists

v_location := 8000;

v_sql := 'DROP VIEW IF EXISTS public.greenplum_get_file_statistics';

v_location := 8100;

    EXECUTE v_sql;


    -- Create a view to get all the datafile statistics

    v_location := 9000;

v_sql :='CREATE VIEW public.greenplum_get_file_statistics AS '

'SELECT '

'  n.nspname || ''.'' || c.relname relation, '

'  osf.segment_id, '

'  split_part(osf.relfilenode, ''.'' :: text, 1) relfilenode, '

'  c.relkind, '

'  sum(osf.size) size '

'FROM '

'  public.greenplum_get_db_file_ext osf '

'  JOIN public.greenplum_get_refilenodes c ON ('

'    c.segment_id = osf.segment_id '

'    AND split_part(osf.relfilenode, ''.'' :: text, 1) = c.relfilenode :: text'

'  ) '

'  JOIN pg_namespace n ON c.relnamespace = n.oid '

'WHERE '

'  osf.relfilenode ~ ''(\d+(?:\.\d+)?)'' '

-- '  AND c.relkind = ''r'' :: char '

'  AND n.nspname not in ('

'    ''pg_catalog'', '

'    ''information_schema'', '

'    ''gp_toolkit'' '

'  ) '

'  AND not n.nspname like ''pg_temp%'' '

'  GROUP BY 1,2,3,4';

v_location := 9100;

    EXECUTE v_sql;


     -- Drop the skew report view view if exists

v_location := 10000;

v_sql := 'DROP VIEW IF EXISTS public.greenplum_get_skew_report';

v_location := 10100;

    EXECUTE v_sql;


    -- Create a view to get all the table skew statistics

    v_location := 11100;

v_sql :='CREATE VIEW public.greenplum_get_skew_report AS '

'SELECT '

' sub.relation relation,'

' (sum(sub.size)/(1024^3))::numeric(15,2) AS vtotal_size_GB,'  --Size on segments

'    (min(sub.size)/(1024^3))::numeric(15,2) AS vseg_min_size_GB,'

'    (max(sub.size)/(1024^3))::numeric(15,2) AS vseg_max_size_GB,'

'    (avg(sub.size)/(1024^3))::numeric(15,2) AS vseg_avg_size_GB,' --Percentage of gap between smaller segment and bigger segment

'    (100*(max(sub.size) - min(sub.size))/greatest(max(sub.size),1))::numeric(6,2) AS vseg_gap_min_max_percent,'

'    ((max(sub.size) - min(sub.size))/(1024^3))::numeric(15,2) AS vseg_gap_min_max_GB,'

'    count(sub.size) filter (where sub.size = 0) AS vnb_empty_seg '

'FROM '

'public.greenplum_get_file_statistics sub'

'  GROUP BY 1';

v_location := 11100;

    EXECUTE v_sql;


    -- Return the data back

    RETURN query (

        SELECT

            *

        FROM public.greenplum_get_skew_report a);


    -- Throw the exception whereever it encounters one

    EXCEPTION

        WHEN OTHERS THEN

                RAISE EXCEPTION '(%:%:%)', v_function_name, v_location, sqlerrm;

END;

$$;


2)  SKEW 리포트 함수 실행  

SELECT * FROM public.greenplum_check_skew() 

where vseg_gap_min_max_percent > 10;


             relation             | vtotal_size_gb | vseg_min_size_gb | vseg_max_size_gb | vseg_avg_size_gb | vseg_gap_min_max_percent | vseg_gap_min_max_gb | vnb_empty_seg

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

 public.order_log_1_prt_p2002     |           0.00 |             0.00 |             0.00 |             0.00 |                    15.50 |                0.00 |             0

 public.greenplum_get_refilenodes |           0.00 |             0.00 |             0.00 |             0.00 |                    42.86 |                0.00 |             0

 public.order_log_1_prt_p2004     |           0.00 |             0.00 |             0.00 |             0.00 |                    12.80 |                0.00 |             0

 public.order_log_1_prt_p2006     |           0.00 |             0.00 |             0.00 |             0.00 |                    19.53 |                0.00 |             0

 public.order_log_1_prt_p2001     |           0.00 |             0.00 |             0.00 |             0.00 |                    14.63 |                0.00 |             0

 public.test_toast2               |           0.00 |             0.00 |             0.00 |             0.00 |                   100.00 |                0.00 |             1

 public.order_log_1_prt_p2005h1   |           0.00 |             0.00 |             0.00 |             0.00 |                    24.32 |                0.00 |             0

 gpkrtpch.region_ix               |           0.00 |             0.00 |             0.00 |             0.00 |                    50.00 |                0.00 |             0

 gpkrtpch.region_pkey             |           0.00 |             0.00 |             0.00 |             0.00 |                    50.00 |                0.00 |             0

 pg_toast.pg_toast_182074         |           0.00 |             0.00 |             0.00 |             0.00 |                   100.00 |                0.00 |             1

 pg_toast.pg_toast_182074_index   |           0.00 |             0.00 |             0.00 |             0.00 |                    50.00 |                0.00 |             0

 gpkrtpch.region                  |           0.00 |             0.00 |             0.00 |             0.00 |                   100.00 |                0.00 |             1

 public.test_toast2_pkey          |           0.00 |             0.00 |             0.00 |             0.00 |                    50.00 |                0.00 |             0

 gpkrtpch.supplier_pkey           |           0.00 |             0.00 |             0.00 |             0.00 |                    20.00 |                0.00 |             0

(14 rows)


Time: 210.008 ms

gpkrtpch=#


3) 각 테이블의 각 세그먼트의 사이즈 확인 

SELECT * FROM public.greenplum_get_file_statistics 

where relation = 'public.order_log_1_prt_p2002';

           relation           | segment_id | relfilenode | relkind | size

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

 public.order_log_1_prt_p2002 |          0 | 209050      | r       |  896

 public.order_log_1_prt_p2002 |          3 | 255681      | r       |  944

 public.order_log_1_prt_p2002 |          1 | 161093      | r       |  872

 public.order_log_1_prt_p2002 |          2 | 161093      | r       | 1032

(4 rows)

Greenplum 제품 알람 공지 수신

Greenplum Product Notifications   * Critical Alerts - 제품 작동에 중요하고 고객 환경에 큰 영향을 미치거나, 많은 고객에게 부정적인 영향을 미칠 수 있는 큰 영향 및/또는 광범위한 소프트웨어 문제. * Pr...