摘要:介绍了13种GaussDB(DWS)单点性能的案例。
1.1 数据歪斜
1.1.1 问题形容
某局点SQL执行慢,波及大表的SQL执行不进去后果。
1.1.2 剖析过程
数据歪斜在很多方面都会有体现:
- gs_ssh –c “df -h”
查看各个数据磁盘的利用率,会有不平衡的景象。失常状况下,利用率最高和利用率最高的磁盘空间相差不大,如果磁盘利用率相差超过了5%就要引起器重。
- 通过期待视图查看作业的运行状况,发现作业总是期待局部DN,或者个别DN。
Select wait_status, count(*) cnt from pgxc_thread_wait_status where wait_status not like ‘%cmd%’ and wait_status not like ‘%none%’ and wait_status not like ‘%quit%’ group by 1 order by 2 desc;
- 慢语句的explain performance显示,基表scan的工夫和行数各个DN之间不平衡。
基表scan的工夫最快的dn耗时5ms,最慢的dn耗时1173ms
数据最多的dn有22831616行,其余dn都是0行,数据有重大歪斜。
- 通过歪斜查看接口能够发现数据歪斜。
select table_skewness('store_sales');
select table_distribution('public','store_sales');
- 通过资源监控发现,个别节点的CPU/IO显著比其余节点高。
1.1.3 问题根因
GaussDB以后反对Hash表和复制表两种散布形式。默认创立的表是Hash散布的,如果不指定散布键,则抉择表的第一列作为散布键。那么这种状况就可能存在歪斜的。
歪斜造成的负面影响十分大。
首先,SQL的性能会十分差,因为数据只散布在局部DN,那么SQL运行的时候就只有局部DN参加计算,没有施展分布式的劣势。
其次,会导致资源歪斜,尤其是磁盘。可能局部磁盘的空间曾经靠近极限,然而其余磁盘利用率很低。
可能呈现局部节点CPU过低等等问题。
1.1.4 解决详情
如何找到歪斜的表:
1.在库中表个数少于1W的场景,间接应用歪斜视图查问以后库内所有表的数据歪斜状况。
1 SELECT * FROM pgxc_get_table_skewness ORDER BY totalsize DESC;
2.在库中表个数十分多(至多大于1W)的场景,因PGXC_GET_TABLE_SKEWNESS波及全库查并计算十分全面的歪斜字段,所以可能会破费比拟长的工夫(小时级),倡议参考PGXC_GET_TABLE_SKEWNESS视图定义,间接应用table_distribution()函数自定义输入,缩小输入列进行计算优化,例如:
表的散布键的抉择办法:
1) 这个列的distinct值比拟大,并且没有显著的数据歪斜。也能够把多列定义成分布列。
怎么看distinct的大小?
select count(distinct column1) from table;
怎么看数据是不是有歪斜?
select count(*) cnt, column1 from table group by column1 order by cnt limint 100;
2) 选用常常做JOIN字段/group by的列,能够缩小STREAM运算。
3) 不好的实际:
散布列用默认值(第一列)
散布列用sequence自增生成
散布列用随机数生成(除非任意列,或者任意两列的组合做散布键都是歪斜的,个别不选用这种办法)。
1.2 统计信息未收集
1.2.1 问题形容
略
1.2.2 剖析过程
- 通过explain verbose/explain performance打印语句的执行打算
- 执行打算中会有语句未收集统计信息的告警,并且通常E-rows估算十分小。
- 上述例子中,在打印的执行打算中有Warning提示信息,提醒有哪些列在这个执行打算中用到了,然而这些列没有统计信息。
在CN的pg_log日志中也有会有相似的Warning信息。
同时,E-rows会比理论值小很多。
1.2.3 问题根因
优化器是基于代价的优化 (Cost-Based Optimization,简称CBO)。在这种优化器模型下,数据库依据表的元组数、字段宽度、NULL记录比率、distinct值、MCV值、HB值等表的特征值,以及肯定的代价计算模型,计算出每一个执行步骤的不同执行形式的输入元组数和执行代价(cost),进而选出整体执行代价最小/首元组返回代价最小的执行形式进行执行。
统计信息是优化器生成执行打算的根底,没有收集统计信息,优化器生成的执行打算会十分差,如果统计信息未收集,会导致多种多样表现形式的性能问题。例如,等值关联走NestLoop,大表broadcast,集群CPU继续增高等等问题。
1.2.4 解决详情
周期性地运行ANALYZE,或者在对表的大部分内容做了更改之后马上执行analyze。
1.3 语句不下推
1.3.1 问题形容
略
1.3.2 剖析过程
1.通过explain verbose打印语句执行打算
2.上述执行打算中有__REMOTE关键字,这就表明以后的语句是不下推执行的。
3.不下推语句在pg_log中会打印不下推的起因。上述语句在CN的日志中会找到相似以下的日志:
1.3.3 问题根因
目前最新版本能够反对绝大多数罕用函数的下推。
不下推函数的场景次要呈现在自定义函数属性定义谬误的场景。
不下推语句的执行形式没有利用分布式的劣势,他的执行过程相当于把大量的数据和计算过程会集到一个节点下来做,因而性能往往十分差。
1.3.4 解决详情
扫视用户自定义函数的provolatile属性是否定义正确。如果定义不正确,要批改对应的属性,使它可能下推执行。
具体判断办法能够参考如下阐明:
函数相干的所有属性都在pg_proc这张零碎表中能够查到。其中与函数是否下推相干的两个属性是provolatile 和 proshippable。
其中provolatile是继承自PG的字段,他的实质含意是形容函数是IMMUTABLE/STABLE/VOLATILE的。
简略来讲,如果一个函数对于同样的输出,肯定有雷同的输入,那么这类函数就是IMMUTABLE的,例如绝大部分的字符串处理函数。
如果一个函数的返回后果在一个SQL语句的调用过程中,后果是雷同的,那么他就是STABLE的。例如工夫相干的处理函数,他的最终显示后果可能与具体的GUC参数相干(例如管制工夫显示格局的参数),这类函数都是STABLE的。
如果一个函数的返回后果可能随着每一次的调用而返回不同的后果。例如nextval,random这种函数,每次调用后果都是不可预期的,那么他就是VOLATILE的。
1.4 not in 和 not exists
1.4.1 问题形容
客户的SQL语句执行慢,执行打算中有NestLoop
1.4.2 问题定位
1.首先察看SQL语句中有not in 语法
2.执行打算中有NestLoop
1.4.3 问题根因
NestLoop是导致语句性能慢的次要起因。
Hashjoin只能做等值关联。NestLoop的条件中有or条件,所以无奈用Hashjoin求解。
导致呈现这个景象的起因是由not in的语义决定的(具体能够参考外网对于not in 和 not exists的介绍)。
1.4.4 解决详情
大多数场景下,客户须要的后果集其实是能够通过not exists取得的,因而上述语句能够通过批改将not in 批改为not exists。
1.5 未分区剪枝
1.5.1 问题形容
三条sql查问慢,查问的分区表总共185亿条数据,查问条件中没有波及分区键
select passtime from 表 where passtime<'2020-02-19 15:28:14' and passtime>'2020-02-18 15:28:37' order by passtime desc limit 10;
select max(passtime) from 表 where passtime<'2020-02-19 15:28:14' and passtime>'2020-02-18 15:28:37';
列存表,分区键为createtime,哈希散布键为motorvehicleid
1.5.2 剖析过程
1.和客户确认局部业务慢,慢的业务中都波及到了同一张表tb_motor_vehicle
2.和客户收集几个典型的慢sql,别离打印执行打算
从执行打算中能够看进去,两条sql的耗时都集中在Partitioned CStore Scan on public.tb_motor_vehicle列存表的分区扫描上
3.和客户确认,该表的分区键为createtime,而波及到的sql中无任何createtime的筛选和过滤条件,根本能够确认是因为慢sql的打算没有走分区剪枝,导致了全表扫描,对于185亿条数据量的表,全表扫描性能会很差。
4.通过在筛选条件中减少分区键过滤条件,优化后的sql和执行打算如下:
SELECT passtime FROM tb_motor_vehicle WHERE createtime > '2020-02-19 00:00:00' AND createtime < '2020-02-20 00:00:00' AND passtime > '2020-02-19 00:00:00' AND passtime < '2020-02-20 00:00:00' ORDER BY passtime DESC LIMIT 10000;
性能从十几分钟,优化到了12秒左右,性能有显著晋升
1.5.3 问题根因
慢sql过滤条件中未波及分区字段,导致执行打算未分区剪枝,走了全表扫描,性能重大裂化
1.5.4 解决详情
在慢sql的过滤条件中减少分区筛选条件,防止走全表扫描
1.6 行数估算过小,走了nestloop
1.6.1 问题形容
查问语句执行慢,卡住无奈返回后果
sql特点是2-3张表left join,而后通过select查问后果,执行打算如下:
1.6.2 剖析过程
1.排查以后的IO,内存,CPU应用状况,没有发现资源占用高的状况
2.查看慢sql的线程期待状态
select * from pg_thread_wait_status where query_id=’149181737656737395’;
依据线程期待状态,并没有呈现都在期待某个DN的状况,初步排除两头后果集偏斜到了同一个DN的状况。
3.到相应的实例节点上,打印期待状态为none的线程堆栈信息如下:
gstack 14104
通过重复打印堆栈信息,发现堆栈在变动,并没有hang死,所以初步判断该问题未性能慢的问题,堆栈中有VecNestLoopRuntime,以及联合执行打算,初步判断是因为统计信息不准,优化器评估后果集较少,打算走了nestloop导致性能降落。
4.对表执行analyze后性能并没有太大改善
5.对sql减少hint敞开索引,让优化器强行走hashjoin,发现hint性能没有失效,起因是hint无奈扭转子查问中的打算
6.通过set enable_indexscan = off;执行打算被扭转,走了Hash Left Join,慢sql在3秒左右跑出后果,满足客户需要。
1.6.3 问题根因
优化器在抉择执行打算时,对后果集评估较小,导致打算走了nestloop,性能降落
1.6.4 解决详情
通过set set enable_indexscan = off;敞开索引性能,让优化器生成的执行打算不走nestloop,而走Hashjoin
1.7 表数据收缩,未清理脏数据
1.7.1 问题形容
数据库性能时快时慢问题
GaussDB 数据库性能时快时慢问题,原先几秒钟的sql,目前20几秒进去,导致前台IOC页面数据加载超时,无奈对用户提供图表显示
1.7.2 剖析过程
- raid卡缓存策略未开启、CPU开启了节能模式,查问并未开启
/opt/MegaRAID/MegaCli/MegaCli64 -LDinfo -Lall –aAll |grep 'Write Cache'(root用户)
cat /proc/cpuinfo |grep MHz
2.和客户确认是局部业务慢,能够提供局部慢sql,打印执行打算,耗时次要在index scan上,狐疑是IO争抢导致,通过监控IO,发现并没有IO资源应用瓶颈。
3.查问以后沉闷sql,发现有大量的create index语句,须要和客户确认该业务是否正当
select * from pg_stat_activity where state !=’idle’ and usename !=’omm’;
4.依据执行打算,发现在局部DN上耗时较高,查问表的歪斜状况,并未发现有歪斜的状况
select table_skewness(‘ioc_dm.m_ss_index_event’);
5.查看内存相干参数,设置不合理,须要优化
单节点总内存大小为256G
max_process_memory为12G,设置过小
shared_buffers为32M,设置过小
work_mem:CN:64M 、DN:64M
max_active_statements: -1(不限度并发数)
设置形式如下:
gs_guc set -Z coordinator -Z datanode -N all -I all -c "max_process_memory=25GB"
gs_guc set -Z coordinator -Z datanode -N all -I all -c "shared_buffers=8GB"
gs_guc set -Z coordinator -Z datanode -N all -I all -c "work_mem=128MB"
6.进一步剖析扫描慢的起因,发现表数据收缩重大,对其中一张8G大小的表,总数据量5万条,做完vacuum full后大小减小为5.6M
1.7.3 问题根因
1.大量表频繁增删改,未及时清理,导致脏数据过多,表数据收缩,查问慢
2.交付时,内存参数设置不合理
1.7.4 解决详情
1.对业务波及到的罕用的大表,执行vacuum full操作,清理脏数据;
2.设置GUC内存参数
1.8 “in 常量”优化
1.8.1 问题形容
简略的大表过滤的SQL语句中有一个“in 常量”的过滤条件,常量的个数十分多(约有2000多个),基表数据量比拟大,SQL语句执行不进去。
1.8.2 剖析过程
1.打印语句的执行打算:
2.执行打算中,in条件还是作为一般的过滤条件存在。这种场景下,最优的执行打算应该是将“in 常量”转化为join操作性能更好。
1.8.3 问题根因
执行打算中,in条件还是作为一般的过滤条件存在。这种场景下,最优的执行打算应该是将“in 常量”转化为join操作性能更好。
1.8.4 解决详情
qrw_inlist2join_optmode能够管制把“in 常量”转join的行为。默认是cost_base的。如果优化器估算不准,可能会呈现须要转化的场景没有做转化,导致性能较差。
这种状况下能够通过设置qrw_inlist2join_optmode为rule_base来躲避解决。
1.9 相干子查问1
1.9.1 问题形容
用户的SQL性能差,执行打算中有SubPlan的关键字
1.9.2 剖析过程
执行打算中有SubPlan,这类语句的性能往往比拟差。
1.9.3 问题根因
执行打算中有SubPlan的语句往往性能比拟差,这是因为,援用SubPlan后果的算子可能须要重复的调用获取这个SubPlan的值,即SubPlan以下的后果要反复执行很屡次。
1.9.4 解决详情
这类问题通常通过改写SQL来躲避。往往这种场景的SQL语句的改写是比拟艰难,而且很容易呈现改写后的后果不统一问题。
因为咱们在比拟高的版本上曾经反对了很多场景想的SubPlan的主动转化为join操作,因而一种比拟不便的思路是打印他在高版本下的执行打算(explain verbose),而后依据explain verbose 演绎进去改写后的SQL语句。
以上述为例,他在高版本的执行打算如下:
那么根据上述信息,SQL语句能够改写为:
为了确认改写后的语句与原来的语句是等价的,能够再次打印改写后的执行打算,比照:
1.11 相干子查问2
1.11.1 问题形容
UPDATE场景下呈现了SubPlan导致语句执行性能差
1.11.2 剖析过程
上述执行打算中有SubPlan,这类语句的性能往往比拟差。
1.11.3 问题根因
执行打算中有SubPlan的语句往往性能比拟差,起因与1.9章节案例相似。
1.11.4 解决详情
上述问题能够通过特定的改写办法来解决:
1.12 单表点查性能差
1.12.1 问题形容
单表查问的场景下,客户预期1s以内返回后果,理论执行耗时超过10s
1.12.2 剖析过程
- 通过抓取问题SQL的执行信息,发现大部分的耗时都在“CStore Scan”
2.剖析出问题的场景:基表是一张十亿级别的表,每晚有批量增量数据入库,同时会有大量的数据荡涤的工作。白天会有高并发的查问操作,查问不波及表关联,并且返回后果都不大。
1.12.3 问题根因
这种场景属于行列存表抉择谬误导致的问题。这种场景应该应用行存表+btree索引。
1.12.4 解决详情
调整表定义,表批改为行存表。同时建设btree索引,索引建设的准则:
- 基于充沛剖析客户SQL的背景上来建设索引。
- 索引要建设的刚刚好,不要有冗余
- 建设组合索引时候,要把过滤性比拟好的列往前放
- 尽可能多的过滤条件都用到索引
1.13 NestLoop+indexscan的实用场景
1.13.1 问题形容
某客户反馈两个表的关联要去秒级返回,其中大表有2.7T,小表有100GB左右,查问后果个别都不大,过滤条件中有过滤性比价好的条件。
1.13.2 剖析过程
- 原始的执行打算:
- 能够看到两个表关联走了HashJoin,次要的耗时在基表扫描和HashJoin操作上。
1.13.3 问题根因
次要的耗时点是在Hashjoin 和基表扫描上,这种状况下能够考用NestLoop+indexScan的打算。
这种打算会把join条件下推到基表扫描上,而后利用基表的索引,提前把数据过滤掉。
1.13.4 解决详情
因为NestLoop+indexScan的打算有一些束缚:
- Join的时候不能有stream(不能通过stream来传递join条件的下推)
- 大表上要有适合的索引。
批改后的执行打算如下:
文末彩蛋:
邻近华为云3月开年洽购季
据外部可靠消息,洽购季中数仓GaussDB(DWS)
包月包年都将有重大优惠,对企业用户尤为敌对!!!
PS:关注数仓GaussDB(DWS)公众号,get最新最全的产品资讯和数仓黑科技,更有超多流动,福利不停歇!欢送拜访数仓GaussDB(DWS)开发者论坛,产品个性随时交换,求助问题还有专家在线实时答疑哦~扫描下方二维码关注我哦↓↓↓
点击关注,第一工夫理解华为云陈腐技术~