TopSQL最佳实践
1、TopSQL简介
在实际的生产环境中,难免会出现一些突发情况,如计划跳变、异常中断、作业长时间执行不结束等,如果已经没有现场,而且也没有工具将当时的作业运行情况记录下来的话,那么事后就要投入更多的人力以及时间成本对错误进行定位和解决,有时还往往定位不到错误出现的地方。为了解决这种情况,GaussDB(DWS)开发了TopSQL功能,对运行中的语句记录(实时TopSQL),对运行完成的语句进行记录(历史TopSQL)。
目前TopSQL功能被用户广泛使用,是性能定位、劣化分析、审计回溯等重要的基石,为用户提供覆盖内存、耗时、IO、网络、空间等多方面的监控能力。 TopSQL可以帮助用户实现下列功能:①确定影响数据库性能的资源最密集的SQL查询;②监控和跟踪SQL查询随时间推移的性能变化;③分析查询执行计划以确定潜在的优化。
2、TopSQL相关视图与GUC参数
TopSQL功能主要通过视图承载,相关视图如下:
视图级别 | 实时 / 历史 | 节点范围 | 查询视图 |
query级别 / perf级别 |
实时 | 当前CN | GS_WLM_SESSION_STATISTICS |
所有CN | PGXC_WLM_SESSION_STATISTICS | ||
历史 |
当前CN | GS_WLM_SESSION_INFO | |
所有CN | PGXC_WLM_SESSION_INFO | ||
所有CN(该视图显示经典字段信息) | PGXC_QUERY_INFO | ||
operator_realtime级别 / operator级别 | 实时 | 当前CN | GS_WLM_OPERATOR_STATISTICS |
所有CN | PGXC_WLM_OPERATOR_STATISTICS | ||
历史 | 当前CN | GS_WLM_OPERATOR_INFO | |
所有CN | PGXC_WLM_OPERATOR_INFO |
TopSQL功能默认打开(use_workload_manager,enable_resource_track,enable_resource_record参数均默认为on),GUC参数详细介绍如下:
- USE_WORKLOAD_MANAGER(ON)
资源管理总开关,TopSQL功能开启该参数需要为on。
-
ENABLE_RESOURCE_TRACK (ON)
是否开启监控功能,实时TopSQL的总开关,关闭之后实时TopSQL将不再进行记录,更不会在历史TopSQL中出现。
-
ENABLE_RESOURCE_RECORD(ON)
设置是否开启资源监控记录归档功能。开启时,对于执行结束的记录,会分别被归档到相应的INFO视图,CN和DN都需要设置上。
-
ENABLE_TRACK_RECORD_SUBSQL(ON)
控制是否记录存储过程、匿名块内部语句(默认为on)(建议820及以上版本开启,TopSQL记录该子语句的前提是:子语句下推到DN执行;子语句执行时间超过resource_track_subsql_duration,目前TopSQL只能记录第一层循环的子语句,多层嵌套循环的子语句不会记录)。
- RESOURCE_TRACK_DURATION(60s)
设置实时TopSQL中记录的语句执行结束后进行历史信息转存的最小执行时间,该时间记录值的判断是包含了排队时间和运行时间(如果在解析优化阶段发生了锁等待,产生的时间不会记录到该参数中),当排队时间+运行时间 > RESOURCE_TRACK_DURATION时,TopSQL历史视图会记录作业信息。CPU和存储资源充足的场景建议设置为0,可记录更全的业务;在QPS高于100场景,可酌情调大,如1-10s。
说明:该参数可支持单位是毫秒、秒、分钟、小时、天,默认单位为秒,参数设置示例如下:
SET resource_track_duration='0.1s';
SET resource_track_duration=0.1;
SET resource_track_duration='0.01min'; # 由于该参数的默认单位是秒,采用四舍五入的方式,因此该处设置的值为1s,而不是0.6s。
- RESOURCE_TRACK_SUBSQL_DURATION(180s)
存储过程内部中子语句转储的最小执行时间。
说明:该参数可支持单位是毫秒、秒、分钟、小时、天,默认单位为秒,参数设置示例如下:
SET resource_track_subsql_duration='0.1s';
SET resource_track_subsql_duration=0.1;
SET resource_track_subsql_duration='0.01min'; # 由于该参数的默认单位是秒,采用四舍五入的方式,因此该处设置的值为1s,而不是0.6s。
-
RESOURCE_TRACK_COST(0)
设置对当前会话的语句进行资源监控的最小执行代价。
-
RESOURCE_TRACK_LEVEL(QUERY)
设置当前会话的资源监控的等级,默认为query级别。
- RESOURCE_TRACK_APPLICATION
设置TopSQL记录指定客户端下发的语句,目前支持设置的客户端为:gs_rewind、cm_agent、pgxc_clean、gs_clean、gs_running_xacts、OM、wlm。设置多个客户端时,相邻的值需用英文逗号隔开
-
TOPSQL_RETENTION_TIME(30)
历史TopSQL中GS_WLM_SESSION_INFO和GS_WLM_OPERATOR_INFO表中数据的保存时间,单位为天(历史TopSQL视图的数据实际是存储在postgres数据库中的dbms_om.gs_wlm_session_info系统表上,该表通过start_time进行分区,每天一个分区,通过参数topsql_retention_time配置默认保留30个分区即30天的记录,定期对pgxc_wlm_session_info的分区进行清理、创建,hash分布且分布键为queryid。如判断该表占用空间较多,可调低该参数,最多30min后表空间可下降)。
- SESSION_HISTORY_MEMORY(100MB)
设置历史查询视图的内存大小,如果语句运行过程中出现"TopSQL lfq is full, failed to save queryid"报错信息,可通过如下SQL查询TopSQL无锁队列总共的内存和已使用的内存。
select * from pgxc_total_memory_detail where nodename like 'cn_%' and memorytype like '%topsql%' order by 1,2;
如果发现某个CN节点topsql_used_memory大于或者即将大于max_topsql_memory,除调大该GUC参数外,可在该CN执行如下SQL,进行手动转储:
CALL pg_catalog.create_wlm_session_info(1);
通过GUC命令设置参数:
gs_guc reload -Z coordinator -Z -N all -I all -c "enable_resource_track=on"
gs_guc reload -Z coordinator -Z -N all -I all -c "resource_track_level=query"
gs_guc reload -Z coordinator -Z -N all -I all -c "enable_resource_record=on"
gs_guc reload -Z coordinator -Z -N all -I all -c "resource_track_duration=0"
gs_guc reload -Z coordinator -Z -N all -I all -c "resource_track_cost=0"
通过管控面设置TopSQL相关参数:
查询TopSQL相关GUC参数设置的常用SQL:
select name,setting from pg_settings where name like '%resource%';
视图常用分析字段:
字段名称 | 字段描述 | 分析出可能的现象 |
block_time | 语句执行前的阻塞时间,包含:语句解析、语句优化时间,以及作业排队时间。 |
A1: block_time较大,而duration值并无明显变化,说明用户作业受其它作业影响,在真正开始执行前进行了较长时间的排队,下一步需要接着查看本数据表,统计起始时间小于start_time、结束时间大于finish_time的作业数量。 A2: block_time较小,而duration值较大,说明用户作业执行时间增加较大原因是自己导致,需要继续分析数据量的变化情况、各DN的执行时间变化。 |
start_time | 语句开始执行时间戳。 | |
finish_time | 语句执行结束时间戳。 | |
duration | 语句执行时间长度。 | |
status | 语句执行的结束状态,正常为finished,异常为aborted。 | 可以查看作业是否正常结束,如果异常,还会有异常原因。 |
abort_info |
语句执行结束状态为aborted时显示异常信息。 | |
min_peak_memory |
语句在所有DN上的最小内存峰值,单位MB。 |
B1: 对于同一个查询,可对比前后几次的内存消耗情况,内存消耗平均值能够反映出数据表的数据量是否有变化,memory_skew_percent值能够侧面反映出相关数据表在各DN上的数据分布是否有倾斜。 并且,query_plan能够直接显示作业的执行计划,对比执行计划是否有变化。 |
max_peak_memory |
语句在所有DN上的最大内存峰值,单位MB。 | |
average_peak_memory |
语句执行过程中的内存使用平均值,单位MB。 |
|
memory_skew_percent |
语句各DN间的内存使用倾斜率。 | |
min_spill_size | 若发生下盘,所有DN上下盘的最小数据量,单位MB。 | C1: 对有大量下盘的查询有显著帮助信息,当下盘量剧增的时候,通常是表数据量有大幅增加,或者是执行计划有问题导致的,结合query_plan能进一步分析,spill_skew_percent可以查看作业是否有严重数据倾斜。 |
max_spill_size |
若发生下盘,所有DN上下盘的最大数据量,单位MB。 | |
average_spill_siz |
若发生下盘,所有DN上下盘的平均数据量,单位MB。 | |
spill_skew_percent |
若发生下盘,DN间下盘倾斜率。 | |
min_dn_time |
语句在所有DN上的最小执行时间,单位ms。 | D1: DN上的执行时间,结合duration数据,如果一个查询的DN执行时间有严重倾斜,那就需要考虑数据表的分区、分布列是否设置合适;不合理的分区、分布列,可能会导致本应分散到多个DN的执行任务被集中到个别DN上执行,执行时间必然大大增加。 |
max_dn_time |
语句在所有DN上的最大执行时间,单位ms。 | |
average_dn_time |
语句在所有DN上的平均执行时间,单位ms。 |
|
dntime_skew_percent |
语句在各DN间的执行时间倾斜率。 |
|
min_cpu_time |
语句在所有DN上的最小CPU时间,单位ms。 | E1: CPU执行时间是分配给改作业的实际执行时间,当duration有明显增加,而平均CPU执行时间无明显变化时,很可能的一个原因是作业执行期间,有多个其它计算密集型作业同时段执行,因CPU抢占的原因,拉长了该作业的执行时长。 |
max_cpu_time |
语句在所有DN上的最大CPU时间,单位ms。 | |
total_cpu_time |
语句在所有DN上的CPU总时间,单位ms。 |
|
cpu_skew_percent | 语句在DN间的CPU时间倾斜率。 | |
min_peak_iops |
语句在所有DN上的每秒最小IO峰值。 | F1: IO是变化最莫测的一个资源,一个作业在数据量不变、内存消耗无变化、CPU执行时间无变化、下盘量无变化的情况下,偏偏duration增加了,那最可能的原因是IO的原因。IO有点独特的是,往往IOPS变小反而反应了作业受其它作业影响,IO跑步起来,拖长了作业执行时间;其它属性通常相反,如:内存、CPU、下盘量,这些值变小通常意味着作业执行变快了。 |
max_peak_iops |
语句在所有DN上的每秒最大IO峰值。 | |
average_peak_iops |
语句在所有DN上的每秒平均IO峰值。 | |
iops_skew_percent |
语句在DN间的IO倾斜率。 | |
query_plan | 语句的执行计划。 | G1: 作业执行计划是否有变化。 |
unique_sql_id | 标识一类语句 | H1: 如果某类语句可能占用较多内存或者CPU资源,需要查杀,可利用gs_append_blocklist(unique_sql_id int8)或者gs_append_blocklist(sql_hash text)函数将该类语句加入黑名单,后续该类语句下发将不再执行。 |
sql_hash |
总结:
-
因数据量变化,导致作业执行时间增加,可以分析A2/B1/D1/G1,进而确认作业查询的数据表是否有明显的数据量增加;
- 由于目前历史TopSQL视图字段信息较多,建议使用PGXC_QUERY_INFO视图查看查询经典字段信息,无需手动过滤无关字段。
-
因其它并发作业抢占,导致作业排队,从而导致作业执行时间增加,可以分析A1/B1/D1,进而查看作业执行的同时期是否有大量并发作业在执行;
-
因其它作业而产生的CPU抢占,导致作业执行时间增加,可以分析A2/D1/E1,进而查看作业执行的同时期是否有大量并发作业在执行;
-
因其它作业而产生的IO抢占,导致作业执行时间增加,可以分析A2/F1,进而查看作业执行的同时期是否有大量并发作业在执行;
- 禁止某一类语句执行,可参考H1。
值得注意的是,发生资源争抢时,可能会出现并发症,即CPU、IO抢占,作业排队现象都会发生,针对并发症问题,可以逐步分析解决,比如:第一步,调整作业执行顺序,减少并发作业数量,减少阻塞时间;第二步,定位出同时段执行的典型计算密集型、存储密集型作业,先移动到其它时间段执行,减少对本作业的影响;第三步,在无其他作业明显干预的情况下,做进一步分析,
注意事项:
- TopSQL不记录白名单和内部语句,但可正常记录超户下发的语句信息,可记录定时任务。
- query和perf级别的topsql监控主要差异点在于query_plan字段,相比于query级别的算子信息,perf级别的query_plan字段增加算子的实际信息,如算子实际内存峰值,内存自动扩展信息,CU,Buffers等统计信息。
- query和perf级别实时TopSQL和历史TopSQL的start_time字段信息含义不一致,实时TopSQL中的start_time表示的是作业下发的时间,历史TopSQL中的start_time表示的是作业真正开始运行的时间。
- 查询历历史TopSQL Query,perf以及算子级别数据时,仅能通过postgres数据库进行访问。
- 实时TopSQL中能够记录的SQL语句的规格是:
- 不记录特殊数据定义语句,如:SET、RESET、SHOW、ALTER SESSION SET、SET CONSTRAINTS语句;
- 记录数据定义语句,例如:执行CREATE、ALTER、DROP、GRANT、REVOKE和VACUUM语句;
- 记录数据操作语句,例如:
- 执行SELECT、INSERT、UPDATE和DELETE语句。
- 执行explain analyze和explain performance场景。
- 使用query级别/perf级别视图。
- 记录函数与存储过程的调用入口语句,当GUC参数enable_track_record_subsql开启的情况下,可记录存储过程的部分内部语句(declare定义语句除外),仅会记录其中下发到DN执行的内部语句,未下发到DN执行的内部语句会被过滤掉;
- 记录匿名块语句,当GUC参数enable_track_record_subsql开启的情况下,可记录匿名块中的部分内部语句,仅会记录其中下发到DN执行的内部语句,未下发到DN执行的内部语句会被过滤掉;
- 记录游标语句,当游标并非从缓存中读取数据,而确实触发语句下发到DN上执行的条件下,该游标语句会被记录,并且会进行语句、执行计划增强,但当游标从缓存中读取数据时,不进行记录;当游标语句在匿名块或者函数中使用时,当游标从DN上读取较多数据但不完全使用时,因当前架构限制,无法记录该游标在DN上的监控信息。对于With Hold游标,该语法执行逻辑特殊,会在事务提交阶段执行实际查询动作,当语句在该阶段执行报错时,作业的aborted状态无法反馈到TopSQL历史表中。
- 重分布过程中的作业不统计;
- JDBC执行的带占位符语句,通常会补齐参数内容,但如果参数和原语句合起来长度超过64KB,则不记录参数,或者如果是轻量化语句,直接下发到DN上执行,不记录参数。如果普通语句语句超过64KB,在TopSQL的query字段记录中将被截断。
- 从8.1.3集群版本开始,query、perf级别TopSQL运行时监控功能已完全不影响查询性能,对当前会话的语句进行资源监控的GUC参数resource_track_cost默认值已修改为0,查询TopSQL实时监控视图时,默认会显示所有正在执行的语句。
- 从8.1.3集群版本开始,对于存储过程中的子语句监控功能,如果在查询TopSQL实时监控视图的会话中,开启控制子语句记录归档功能的GUC参数enable_track_record_subsql,不论业务语句中是否开启子语句监控开关,查询TopSQL实时监控视图的结果都能看到执行语句的子语句运行信息。
- 关于存储过程中子语句的监控功能即enable_track_record_subsql,8.1.3集群版本中建议不要全面开启,由于没有按时间过滤子语句的功能,全面开启可能会记录过多子语句,导致归档的监控表占用大量磁盘空间;8.1.3集群版本建议仅用于查询实时监控信息,或对个别存储过程业务做定位分析时,仅开启对应会话中的参数。8.2.1版本新增GUC参数resource_track_subsql_duration(默认值为180秒),可以通过执行时间过滤需要归档的子语句,用户可以按需调整该值大小。
- 由于规格限制,对于未下盘的主语句,TopSQL历史表中的记录会有延时,等待下次作业下发时才会显示在TopSQL历史表中。
- 从8.2.1.200集群版本开始,新增operator_realtime级别TopSQL运行时监控,提供算子级实时监控的能力,开启此级别的监控可以查询语句的执行计划以及具体执行信息,查询TopSQL算子级实时监控视图时,默认会显示所有正在执行的语句。但是对于存储过程和游标场景,暂时不支持显示算子级实时监控信息。另由于查询所有语句的信息对于CN内存压力较大,为了不影响作业性能,为用户提供查询单个语句的函数pg_stat_get_wlm_realtime_operator_info(queryid),可以通过该函数查询指定语句的算子执行信息,
- operator_realtime级别TopSQL运行时监控对于CN轻量化和存储过程的情况,暂时不支持。另由于算子执行速度较快的原因,对于算子信息的显示会有一定滞后性。
- query级别的作业监控和operator的算子监控中的spill_size字段,由于统计维度不同,会有一定差异,query级别监控监控的语句实际下盘文件大小,算子监控的是具体算子在逻辑层IO读写的数据量。
- 当GUC参数enable_stream_operator设置为off状态时,算子执行信息存在显示不准的情况。
- 在813版本中,除初始用户外,enable_gtm_free开启且关联队列不管控情况下,用户作业不进入资源管控。此时实时与历史TopSQL均不记录该用户下发的作业。
TopSQL视图warning字段解析:
warning告警信息分类 | 具体信息 | 解决方法 |
下盘量过大或过早下盘 |
The max spill size exceeds the alarm size xxxMB |
下盘可能是因为缓冲区设置得过小,也可能是因为表的连接顺序或连接方式不合理等原因,要结合具体的 SQL 进行分析。可以通过改写 SQL 语句,或者 HINT 指定连接方式等手段来解决。 |
The max broadcast size exceeds the alarm size xxxMB | ||
Early spill | ||
Spill times is greater than 3 | ||
Spill on memory adaptive | ||
Hash table conflict | ||
统计信息 |
Nestloop in hashjoin | 有可能统计信息不准,及时analyze相关业务表 |
Table whose delta data exceeds 10% cannot be analyzed on VW | 弹性vw部分场景下不支持analyze,此为规格 | |
Replication table cannot be analyzed on VW in temporary table sampling mode. | ||
Table cannot be analyzed on VW when enable_parallel_analyze is disabled in temporary table sampling mode. | ||
Replication table with more than 100,000 rows cannot be analyzed on VW. | ||
弹性vw |
Concurrent scaling is not supported because the statement is in a transaction block. | 弹性vw负载均衡功能开启后,作业未能路由到弹性vw的原因,此为规格 |
Concurrent scaling is not supported because the statement is a stored procedure. | ||
Concurrent scaling is not supported because the statement is not of the DML type. | ||
Concurrent scaling is not supported because the statement involves tables except V3 tables and foreign tables. | ||
Concurrent scaling is not supported because the statement does not support the cudesc streaming. | ||
Concurrent scaling is not supported because the resource pool associated with the statement disables the concurrency extension parameter. | ||
Concurrent scaling is not supported because the statement does not support cn retry. | ||
物化视图 | has others update base table, can not active matview. | 物化视图刷新告警,此为规格 |
3、通过TopSQL识别资源密集SQL
- 识别stream数量多的语句
select *,(length(query_plan) - length(replace(query_plan, 'Streaming', ''))) / length('Streaming') as stream_count FROM pgxc_wlm_session_info ORDER BY stream_count DESC limit 100;
- 识别内存占用高的语句
select * from pgxc_wlm_session_info where start_time > 'xxxx-xx-xx' and start_time < 'xxxx-xx-xx' order by max_peak_memory desc limit 100;
- 识别需要优化的语句
select * from pgxc_wlm_session_info where start_time > 'xxxx-xx-xx' and start_time < 'xxxx-xx-xx' and warning is not null order by duration desc limit 100;
- 识别执行时间长的语句
select * from pgxc_wlm_session_info where start_time > 'xxxx-xx-xx' and start_time < 'xxxx-xx-xx' order by duration desc;
- 识别不下推的语句
select * from pgxc_wlm_session_info where start_time > 'xxxx-xx-xx' and start_time < 'xxxx-xx-xx' and warning like ‘%can not be shipped%’ order by max_peak_memory desc;
- 识别高CPU语句
select * from pgxc_wlm_session_info where start_time > 'xxxx-xx-xx' and start_time < 'xxxx-xx-xx' order by max_cpu_time desc;
- 识别下盘量大的语句
select * from pgxc_wlm_session_info where start_time > 'xxxx-xx-xx' and start_time < 'xxxx-xx-xx' order by max_cpu_time desc;
- 识别未做analyze的语句
select * from pgxc_wlm_session_info where start_time > 'xxxx-xx-xx' and start_time < 'xxxx-xx-xx' and warning ilike '%statistics%';
4、 PERT作业级级别TopSQL监控
现网中有概率出现某一个SQL原先执行比较快,后来发现该语句执行时间变长,此时就需要利用TopSQL中的query_plan以及其他资源信息进行分析定位,毋庸置疑,query_plan中的信息越详细,越接近于explain performance,定位过程就更容易。query级别与perf级别的TopSQL差异主要在query_plan,perf级记录更详细执行信息,较query级性能损耗5%以内,perf级别的TopSQL的query_plan字段可显示算子的时间actual_time,memory,rows和buffer等信息。
5、OPERATOR算子级TopSQL监控
在SQL执行过程中,有些用户更希望能对算子执行进度进行监控,对于长时间运行的SQL,能够看出哪个算子执行时间长,通过算子执行时间和已处理行数等信息,确定是否需要查杀SQL,此时需要将RESOURCE_TRACK_LEVEL参数设置为OPERATOR。
算子监控可以将SQL执行过程的算子监控数据以可视化的方式呈现出来,以便用户更加直观地了解算子的运行情况和性能表现。算子监控主要有以下价值:
- 提升用户体验:通过可视化的方式呈现算子执行信息,用户可以更加直观地了解算子的运行情况和性能。
- 性能优化:通过对算子监控数据的可视化分析,可以发现算子运行中的瓶颈和问题,从而及时进行优化和调整,提高算子的运行效率。
- 故障排查:通过对算子监控数据的可视化分析,可以及时发现算子运行中的问题和异常,从而及时进行修复和维护,提高SQL的可维护性。
- 提高算子的可扩展性:通过对算子监控数据的可视化分析,可以发现算子运行中的瓶颈和问题,从而及时进行优化和调整,提高算子的可扩展性,为后续的业务发展提供支持。
OPERATOR算子监控和QUERY/PERF语句监控功能类似,均包含实时和历史二种形态,包含静态和动态二类信息:
- 语句静态信息是语句在真正执行前就已经由优化器生成的信息,如执行计划plan_node_name,queryid,预估行数estimated rows等信息。可用来分析生成的执行计划是否合适。
- 语句动态信息是语句在执行器中执行过程中所占用的资源信息,如算子执行进度progress、内存peak_memory、算子下盘spill_size、网络net_size、磁盘IO(read_bytes、write_bytes),CPU(cpu_time)等不同DN的实时的信息记录。可用来分析语句执行过程中的进度和资源消耗情况,通过该字段可以分析出语句在运行是消耗较久的在什么地方,便于后续优化。
功能展示:我们下发某个查询,在另一个会话中查询实时算子视图pgxc_wlm_operator_statistics,结果如下:
6、TopSQL与其他视图交互
不同视图从不同维度统计业务在数据库中的运行状态,因为或多或少都包含部分同类字段,可用于后续关联分析,此处给出历史TopSQL视图常交互的其他视图:
使用示例:如果某个语句在历史TopSQL 历史pgxc_wlm_session_info视图中显示以往该作业很快就能正常运行完成,但是此时查杀pgxc_stat_activity发现该语句运行很长时间没有结束,如下图所示,则此时可能有异常,可利用以下步骤进行定位:
常用定位过程如下所示:
步骤1:查询pgxc_stat_activity活跃视图,找出长时间运行不结束的异常作业
select coorname, usename, client_addr, now()-query_start as dur, state, enqueue, waiting, pid, query_id, substr(query,1,150) FROM pgxc_stat_activity WHERE usename not in ('omm','Ruby') and state = 'active' ORDER BY dur DESC limit 100;
步骤2:根据步骤1得到的query信息,查询历史TopSQL视图,比较以往和现在的运行情况,如果以前运行时间很快,但当前语句运行时间很长未结束,则可考虑该语句已发生异常(历史topsql视图按天分区,查询时尽量带start_time条件)
select * from pgxc_wlm_session_info where start_time > '2024-08-22 00:00' and start_time < '2024-08-24 00:00' and query ilike '%XXXXXXXXX%' order by start_time;
步骤3:根据步骤1得到的query_id查询等待视图pgxc_thread_wait_status,得到作业线程号lwtid,并打出作业堆栈进行分析
select * from pgxc_thread_wait_status where query_id = xxx;
select * from gs_stack('nodename',tid); # 本节点可直接 \! gstack lwtid
7、TopSQL原理介绍
作业下发执行后,内核通过打桩记录作业的各项资源信息,如内存、CPU、下盘、IO和网络信息等,作业执行完成后该资源信息后先存在无锁队列中,资源管理后台辅助线程将该数据信息定期转储到dbms_om.gs_wlm_session_info系统表中,后续通过topsql_retention_time定期老化数据。
8、TopSQL实践
通常情况下,TopSQL记录的信息较多, 查询时可使用start_time做条件,避免全表查询,且使用limit对结果集大小限制,防止结果集过大导致客户端OOM。
案例1:某客户集群出现系统级性能问题,CPU持续飚高,业务受阻。
通过TopSQL历史视图查询到有10+业务SQL存在stream数超过100,判断为CPU高的原因:
postgres=# select *,(length(query_plan) - length(replace(query_plan, 'Streaming', ''))) / length('Streaming') as stream_count FROM pgxc_wlm_session_info ORDER BY stream_count DESC limit 100;
针对此业务SQL进行下线并进行差分优化后,问题解决。
案例2:业务语句性能下降,业务曾经比较快,后来变慢了
因为topsql记录了一些语句的执行情况和资源消耗情况,在定位性能问题的时候非常有帮助,比如周期执行的sql,突然有一天变慢了,我们可以通过分析语句的执行时间和阻塞时间判断是语句被阻塞了(排队等)还是执行的慢了,通过记录的执行计划分析语句为什么慢了,是不是当时的统计信息统计不准,还是没有对表做analyze,也可以看下盘量大小分析是不是下盘量大造成的性能变慢。
步骤1:通过pgxc_wlm_session_info视图确认历史的SQL信息(注:历史topsql视图按天分区,查询时尽量带start_time条件)
select * from pgxc_wlm_session_info where start_time > '2023-08-22 00:00' and start_time < '2023-08-24 00:00' and query ilike '%XXXXXXXXX%' order by start_time;
步骤2:根据作业的sql_hsah信息确定作业的历史执行情况,借助历史TopSQL的资源信息和query_plan字段分析作业性能劣化原因。
select start_time, block_time, duration, sql_hash, warning, max_peak_memory, max_spill_size, query_plan from pgxc_wlm_session_info were start_time > 'xxxx-xx-xx xx:xx' and sql_hash = 'xxx' order by start_time desc limit 10;
找到对应的快慢语句后,对比其执行计划query_plan,发现执行计划跳变严重
步骤3:对相应的表做analyze后,恢复合理计划,语句性能恢复。
统计信息不准,导致计划跳变,是十分常见语句变慢原因,analyze不影响读写,遇见语句变慢可预先做analyze。
analyze dwrdim_dw1.dwr_dim_region_rc_d;
案例3:作业长时间运行不结束
在作业无排队无死锁正常运行期间,发现作业长时间不结束,此时可查看算子级别的实时TopSQL监控,能够看出哪个算子执行时间长,通过算子执行时间和已处理行数等信息,确定是否需要查杀SQL。
步骤1:开启实时算子监控:set resource_track_level = 'operator_realtime';
步骤2:根据需要查杀作业
select * from pg_terminate_backend(xxx); # 入参为pid
案例4:作业整体使用内存较高,需分析算子内存使用情况
当发现作业内存整体使用较高,query级别的TopSQL无法记录算子的实际资源信息,此时可以设置TopSQL的监控级别为perf,query级别与perf级别的TopSQL差异主要在query_plan,perf级记录更详细执行信息,较query级性能损耗5%以内,perf级别的TopSQL的query_plan字段可显示算子的时间actual_time,memory,rows和buffer等信息。
步骤1:开启perf级别TopSQL监控::set resource_track_level = 'perf';
步骤2:作业执行结果后,查询历史TopSQL视图pgxc_wlm_session_info查看各个算子的内存使用情况。
9、参考文献
- 点赞
- 收藏
- 关注作者
评论(0)