分布式数据存储倾斜快速检测

网友投稿 904 2022-05-29

前言

数据存储倾斜(即图中1-4被占用存储资源不均衡)是Shared nothing分布式架构下的重要难题,它破坏了MPP架构中各个节点对等的要求,导致倾斜节点所需存储及计算资源都远大于其他节点,进而导致性能下降(木桶效应)、full disk或oom等严重问题。

技术背景

目前各类分布式数据库厂商都有提供存储倾斜的检测工具,常用方法主要有计算表的COUNT,计算表的SIZE和通过统计信息计算这三种,下面以在GaussDB(DWS)分布式数据库产品为例,分别介绍这三种方式的优劣:

方法一:通过表的COUNT计算倾斜

方案:例如使用table_skewness函数,其内部通过统计表在各节点的COUNT数实现

分布式数据存储倾斜快速检测

postgres=# select dnname,num from table_skewness('mytable') order by dnname;   dnname   | num ---------------+------  datanode1  | 4800  datanode2  | 5216  datanode3  | 5792  datanode4  | 5568  datanode5  | 5152  datanode6  | 5472 (6 rows)

优点:简单粗暴,适用表数据量小且UPDATE/DELETE少的表;

缺点:数据量大的场景计算表的COUNT比较耗时;脏数据占存储和SCAN消耗但不会统计;

方法二:通过表的SIZE计算倾斜(推荐)

方案:例如使用table_distribution函数,其内部通过统计表在各节点的SIZE大小实现

postgres=# select nodename,dnsize from table_distribution('public','mytable') order by nodename;  nodename  | dnsize -------------+--------  datanode1 | 221184  datanode2 | 229376  datanode3 | 253952  datanode4 | 253952  datanode5 | 229376  datanode6 | 253952 (6rows)

优点:实时性好;准确度高;相比计算COUNT速度快;

缺点:表对应数据文件多的场景性能会受影响,当前实测100+节点场景影响在可接受范围

方法三:通过统计信息计算倾斜

方案:使用pg_class中reltuples/relpages以及统计信息来计算倾斜

CREATE OR REPLACE FUNCTION PUBLIC.pgxc_analyzed_tuples (     OUT schemaname text,     OUT tablename text,     OUT dn_name text,     OUT tuples real ) RETURNS SETOF record AS $$ DECLARE     datanode_rd     record;     fetch_tuples    record;     fetch_dn        text;     fetch_tuple_str text; BEGIN     fetch_dn := 'SELECT node_name FROM pg_catalog.pgxc_node WHERE node_type=''D'' order by node_name';     FOR datanode_rd IN EXECUTE(fetch_dn) LOOP         dn_name         :=  datanode_rd.node_name;         fetch_tuple_str := 'EXECUTE DIRECT ON (' || dn_name || ') ''SELECT n.nspname, c.relname, c.reltuples                    FROM pg_catalog.pg_class c                    INNER JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace                    where c.oid >16384 AND c.relkind = ''''r''''                     and n.nspname <> ''''cstore'''' and n.nspname <> ''''pmk''''                     and n.nspname <> ''''pg_catalog''''''';         FOR fetch_tuples IN EXECUTE(fetch_tuple_str) LOOP             tuples    := fetch_tuples.reltuples;             schemaname := fetch_tuples.nspname;             tablename  := fetch_tuples.relname;             return next;         END LOOP;     RAISE INFO 'Finished fetching stats info from DataNode % at %',dn_name, clock_timestamp();     END LOOP;     return; END; $$ LANGUAGE 'plpgsql' ROWS 1000000; postgres=# select dn_name,tuples from public.pgxc_analyzed_tuples() where tablename='mytable';   dn_name | tuples -------------+--------  datanode1 | 4800  datanode2 | 5216  datanode3 | 5792  datanode4 | 5568  datanode5 | 5152  datanode6 | 5472 (6 rows)

优点:计算过程不需要实时SCAN,只需要通过已有统计信息来计算,速度最快。

缺点:强依赖实时ANALYZE统计信息来保证实时性;不包含实际占用存储空间和SCAN 消耗的脏数据统计,准确度不如方法二。

小结

以上三种方法主要针对单个表的倾斜查询,各有优劣,这里比较推荐准确度最高速度居中的方法二,并基于此方法实现了系统视图PGXC_GET_TABLE_SKEWNESS用于查询库内所有表的存储分布情况,例:

postgres=# select * from PGXC_GET_TABLE_SKEWNESS; schemaname | tablename | totalsize | avgsize  | maxratio | minratio | skewsize | skewratio | skewstddev ------------+------------+-------------+------------+------------+------------+-----------+------------+------------  public  | orders  | 705413120 | 117568853 |  .167  |  .166  | 278528  |  0.000  |  95628  public  | mytable  | 1441792  | 240299  |  .176  |  .153  | 32768  |  .023  |  15253  public  | customer | 131579904 | 21929984 |  .167  |  .166  | 131072  |  .001  |  46050  public  | part   | 101646336 | 16941056 |  .167  |  .166  | 114688  |  .001  |  38772  public  | supplier | 8552448  | 1425408  |  .168  |  .166  | 16384  |  .002  |  8974  public  | lineitem | 3351937024 | 558656171 |  .167  |  .166  | 1302528 |  0.000  |  516984  public  | partsupp | 461922304 | 76987051 |  .167  |  .166  | 401408  |  .001  |  148130 (7 rows)

后面将语句基于table_distribution函数及PGXC_GET_TABLE_SKEWNESS视图,介绍如何在真实业务场景中及早、快速定位到存储倾斜的表。

实战场景

从早发现、快定位、勤检查三个角度,介绍如何在实际业务场景中最大程度避免数据存储倾斜带来的影响。

早发现:数据导入场景即时检测

当前我们支持在数据导入过程对DN导入行数进行统计,导入完成后计算倾斜率,超过一定阈值时,立即进行告警。倾斜率通过( DN导入行数最大值-DN导入行数最小值) /导入总行数计算,方法如下:

1、开启即时检测的参数

table_skewness_warning_rows:表倾斜告警最小行数,取值范围0~ INT_MAX,默认值100000,表示当导入总行数超过该值与导入DN数之积时,才可能触发告警,避免小数据量导入的场景进行无意义的告警。

table_skewness_warning_threshold:表倾斜告警阈值,取值范围0~1.0,默认值为0,表示当DN返回行数的最小值和最大值的比例小于指定的倾斜告警阈值时,进行告警。

2、执行导入(INSERT或COPY)

当导入数据出现倾斜,执行SQL和日志中会发出告警,告警信息包括表名、最小行数、最大行数、总行数、平均行数、倾斜率,以及提示信息(检查数据分布或者修改参数)。

WARNING: Skewness occurs, table name: xxx, min value: xxx, max value: xxx, sum value: xxx, avg value: xxx, skew ratio: xxx HINT: Please check data distribution or modify warning threshold

快定位:磁盘满场景快速定位倾斜表

出现磁盘满场景,在表数量非常多的情况下,全量排查哪些表倾斜非常耗时,我们支持使用如下方式快速定位倾斜表:

1、查询近期发生过数据变更的表

通过pg_stat_get_last_data_changed_time(oid)函数查询出近期发生过数据变更的表,基于表的最后修改时间只在进行IUD操作的CN记录,要查询库内1天(间隔可在函数中调整)内被修改的所有表,可以使用如下封装函数:

CREATE OR REPLACE FUNCTION get_last_changed_table(OUT schemaname text, OUT relname text) RETURNS setof record AS $$ DECLARE     row_data record;     row_name record;     query_str text;     query_str_nodes text; BEGIN     query_str_nodes := 'SELECT node_name FROM pgxc_node where node_type = ''C''';     FOR row_name IN EXECUTE(query_str_nodes) LOOP        query_str := 'EXECUTE DIRECT ON (' || row_name.node_name || ') ''SELECT b.nspname,a.relname                FROM pg_class a INNER JOIN pg_namespace b on a.relnamespace = b.oid where                pg_stat_get_last_data_changed_time(a.oid)                 BETWEEN current_timestamp - 1 AND current_timestamp;''';       FOR row_data IN EXECUTE(query_str) LOOP         schemaname = row_data.nspname;         relname = row_data.relname;         return next;       END LOOP;     END LOOP;     return; END; $$ LANGUAGE plpgsql;

2、查看近期数据变更的表的分布情况

postgres=# SELECT table_distribution(schemaname,relname) FROM get_last_changed_table() limit 6;         table_distribution -----------------------------------  (public,mytable,datanode1,221184)  (public,mytable,datanode2,229376)  (public,mytable,datanode3,253952)  (public,mytable,datanode4,253952)  (public,mytable,datanode5,229376)  (public,mytable,datanode6,253952) (6 rows)

勤检查:常规数据倾斜巡检

1、在库中表个数比较少(<1W)场景

直接使用PGXC_GET_TABLE_SKEWNESS视图来查询当前库内所有表的数据倾斜情况。

2、在库中表个数非常多(>1W)场景

PGXC_GET_TABLE_SKEWNESS涉及全库查并计算非常全面的倾斜字段,所以可能会花费比较长的时间(小时级),建议参考PGXC_GET_TABLE_SKEWNESS视图定义,直接使用table_distribution()函数自定义输出,减少输出列进行计算优化,例如:

postgres=# SELECT schemaname,tablename,max(dnsize) AS maxsize, min(dnsize) AS minsize postgres-# FROM pg_catalog.pg_class c postgres-# INNER JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace postgres-# INNER JOIN pg_catalog.table_distribution() s ON s.schemaname = n.nspname AND s.tablename =c.relname postgres-# INNER JOIN pg_catalog.pgxc_class x ON c.oid = x.pcrelid AND x.pclocatortype = 'H' postgres-# GROUP BY schemaname,tablename; schemaname | tablename | maxsize | minsize ------------+-------------+-----------+-----------  public  | orders   | 117686272| 117407744  public  | mytable  | 253952  | 221184  public  | customer  | 21979136 | 21848064  public  | part    | 16982016 | 16867328  public  | supplier  | 1433600 | 1417216  public  | lineitem  | 559284224| 557981696  public  | partsupp  | 77094912 | 76693504 (7 rows)

总结

分布式框架下的倾斜是个大课题,本文主要针对存储倾斜(不包含计算倾斜)重点分享我们在业务中如何尽快发现倾斜、定位倾斜,希望能给大家提供一些思路和帮助。

DWS 分布式 EI企业智能

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Leecode-215:数组中的第K个最大元素【堆heaq排序】
下一篇:百度Apollo开发平台调研
相关文章