Greenplum 調優--數據傾斜排查(二)


上次有個朋友咨詢我一個GP數據傾斜的問題,他說查看gp_toolkit.gp_skew_coefficients表時花費了20-30分鍾左右才出來結果,后來指導他分析原因並給出其他方案來查看數據傾斜。

其實很多朋友經常使用如下的方式來檢查數據分布:

select gp_segment_id,count(1) from person_info group by 1;  

但是這種方法太簡單,只有判斷存儲是否傾斜,不能夠去對數據處理是否會出現傾斜做出判斷。而且判斷的維度很少,不直觀。

后來Greenplum提供了gp_toolkit.gp_skew_coefficients等工具來進行檢查判斷。

首先我們來看一下gp_toolkit.gp_skew_coefficients這個視圖的邏輯:

my_db_safe=# \d+ gp_toolkit.gp_skew_coefficients 

View "gp_toolkit.gp_skew_coefficients"

View definition:  SELECT skew.skewoid AS skcoid, pgn.nspname AS skcnamespace, pgc.relname AS skcrelname, skew.skewval AS skccoeff   

FROM gp_toolkit.__gp_skew_coefficients() skew(skewoid, skewval)   

JOIN pg_class pgc ON skew.skewoid = pgc.oid   

JOIN pg_namespace pgn

ON pgc.relnamespace = pgn.oid;

 

當我們使用視圖gp_toolkit.gp_skew_coefficients來檢查表數據傾斜時,該視圖會基於表的行數據量來檢查,如果表數據量越大,檢查時間就會越長。

select * from  gp_toolkit.gp_skew_coefficients;

 

其中skccoeff 通過存儲記錄均值計算出的標准差,這個值越低說明數據存放約均勻,反之說明數據存儲分布不均勻,要考慮分布鍵選擇是否合理。 

另外一個視圖gp_toolkit.gp_skew_idle_fractions 通過計算表掃描過程中,系統閑置的百分比,幫助用戶快速判斷,是否存在分布鍵選擇不合理,導致數據處理傾斜的問題。

 

siffraction字段表示表掃描過程中系統閑置的百分比,比如0.1表示10%的傾斜。

結合上面兩個視圖的結果,我們可以看到某些表的結論是數據傾斜很厲害,

比如ao_schedule表,但是實際上這些表是因為數據量太少,只有幾條,那只能分布在某幾個segment節點上,其他segment節點都沒有數據,

比如:

select gp_segment_id,count(1) from os.ao_schedule group by 1;

 

可以看出,os.ao_schedule表只有5條數據,所有判斷數據傾斜時要結合多方面來判斷。

本文章會介紹一種替代上面兩個視圖低效查詢數據傾斜的方式。

解決方案的原理:這次方案也是使用視圖來觀察每個segment上的每個表的文件大小。

它將僅僅輸出那些表至少一個segment大小比預期的大20%以上。 下面一個工具,一個能夠快速給出表傾斜的信息。

執行如下的創建函數的SQL:

CREATE OR REPLACE FUNCTION my_func_for_files_skew() RETURNS void AS  $$ DECLARE      v_function_name text := 'my_create_func_for_files_skew';     v_location_id int;     v_sql text;     v_db_oid text;     v_number_segments numeric;     v_skew_amount numeric; BEGIN     --定義代碼的位置,方便用來定位問題--                    v_location_id := 1000;          --獲取當前數據庫的oid--             SELECT oid INTO v_db_oid      FROM pg_database      WHERE datname = current_database();       --文件傾斜的視圖並創建該視圖--           v_location_id := 2000;     v_sql := 'DROP VIEW IF EXISTS my_file_skew_view';          v_location_id := 2100;    EXECUTE v_sql;        --保存db文件的外部表並創建該外部表--         v_location_id := 2200;    v_sql := 'DROP EXTERNAL TABLE IF EXISTS my_db_files_web_tbl';     v_location_id := 2300;    EXECUTE v_sql;     --獲取 segment_id,relfilenode,filename,size 信息--         v_location_id := 3000;    v_sql := 'CREATE EXTERNAL WEB TABLE my_db_files_web_tbl ' ||            '(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"] "/' || v_db_oid ||             E'/" $9 "\\t" $5''''}'' on all ' || 'format ''text''';     v_location_id := 3100;    EXECUTE v_sql;     --獲取所有primary segment的個數--         v_location_id := 4000;    SELECT count(*) INTO v_number_segments     FROM gp_segment_configuration     WHERE preferred_role = 'p'     AND content >= 0;     --如果primary segment總數為40個,那么此處v_skew_amount=1.2*0.025=0.03--        v_location_id := 4100;    v_skew_amount := 1.2*(1/v_number_segments);        --創建記錄文件傾斜的視圖--        v_location_id := 4200;    v_sql := 'CREATE OR REPLACE VIEW my_file_skew_view AS ' ||             'SELECT schema_name, ' ||             'table_name, ' ||             'max(size)/sum(size) as largest_segment_percentage, ' ||             'sum(size) as total_size ' ||             'FROM    ( ' ||             'SELECT n.nspname AS schema_name, ' ||             '      c.relname AS table_name, ' ||             '      sum(db.size) as size ' ||             '      FROM my_db_files_web_tbl db ' ||             '      JOIN pg_class c ON ' ||             '      split_part(db.relfilenode, ''.'', 1) = c.relfilenode ' ||             '      JOIN pg_namespace n ON c.relnamespace = n.oid ' ||             '      WHERE c.relkind = ''r'' ' ||             '      GROUP BY n.nspname, c.relname, db.segment_id ' ||             ') as sub ' ||             'GROUP BY schema_name, table_name ' ||             'HAVING sum(size) > 0 and max(size)/sum(size) > ' ||  --只記錄大於合適的才輸出---             v_skew_amount::text || ' ' ||              'ORDER BY largest_segment_percentage DESC, schema_name, ' ||             'table_name';     v_location_id := 4300;    EXECUTE v_sql;      EXCEPTION        WHEN OTHERS THEN            RAISE EXCEPTION '(%:%:%)', v_function_name, v_location_id, sqlerrm;END;$$ language plpgsql;

然后我們執行函數,創建相關的對象:

select my_func_for_files_skew();

 

 這時我們就可以查看我們計划的傾斜表:

select * from my_file_skew_view ;

 

我們也可以選擇按照傾斜度的大小進行排序:

select * from my_file_skew_view order by largest_segment_percentage desc;

根據查看結果,需要我們關注的是largest_segment_percentage這個字段的值,越靠近1說明一個segment上面的數據比集群的其他節點更多,

比如os.ao_variables表的largest_segment_percentage為0.875,說明87.5%的數據在一個segment上面。

 

我們可以驗證一下:

 

很顯然,共有7條數據(總共8條數據)都在gp_segment_id為35的segment上面,占87.5%。

如果大家對Greenplum數據庫熟悉的話,就會發現上面工具的一個問題,即表膨脹。

當我們對表執行DML操作時,對於刪除的空間並沒有立馬釋放給操作系統,所以我們的計算結果可能會包含這部分大小。

個人建議在執行這個查看表文件傾斜之前,對需要統計的表進行Vacuum回收空間,或使用CTAS方式進行表重建。

另外補充一點,如果你想對單個表進行統計傾斜度時,可以修改函數,添加一個參數,用來傳入表名或表的oid即可。

 

整理自:

https://blog.csdn.net/jiangshouzhuang/article/details/51792580

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM