分布式数据存储倾斜快速检测
【摘要】 本文主要分享快速、准确识别数据存储倾斜的方法。
前言
数据存储倾斜(即图中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)
总结
分布式框架下的倾斜是个大课题,本文主要针对存储倾斜(不包含计算倾斜)重点分享我们在业务中如何尽快发现倾斜、定位倾斜,希望能给大家提供一些思路和帮助。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
彩虹上的水瓶座2020/07/10 09:05:521楼编辑删除举报