分布式数据存储倾斜快速检测
前言
数据存储倾斜(即图中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)
总结
分布式框架下的倾斜是个大课题,本文主要针对存储倾斜(不包含计算倾斜)重点分享我们在业务中如何尽快发现倾斜、定位倾斜,希望能给大家提供一些思路和帮助。
- 点赞
- 收藏
- 关注作者
评论(0)