摘要:通常在运维监控出现CPU使用率较高、P80/P95指标较高、慢SQL数量上升等现象,或者业务出现超时报错时,优先应排查是否出现慢SQL。
本文分享自华为云社区《GaussDB慢SQL常见定位处理手段》,作者:酷哥。
通常在运维监控出现CPU使用率较高、P80/P95指标较高、慢SQL数量上升等现象,或者业务出现超时报错时,优先应排查是否出现慢SQL。
查询当前执行时间TOP10的SQL,识别长时间未结束的SQL后可以手动中止。
select a.pid, a.sessionid, a.datname, a.usename, a.application_name, a.client_addr, a.xact_start, a.query_start, (now() - a.query_start)::text as query_runtime, a.unique_sql_id, w.wait_status, w.wait_event, w.locktag, w.lockmode, w.block_sessionid, a.query from pg_stat_activity a join pg_thread_wait_status w on a.sessionid = w.sessionid where a.pid <> pg_backend_pid() and a.state = 'active' and a.client_addr is not null order by query_runtime desc;
根据查询结果,如果是等待锁,可以结合锁等待信息进一步分析,其他情况可以根据unique_query_id关联WDR报告、statement视图进一步分析慢的根因。
思路:根据CPU、慢SQL等监控指标,定位慢SQL出现的时间范围,通过以下几种方式进一步分析。
通过导出对应时间段的WDR报告,可以分析耗时较长的SQL,WDR报告生成方法参见产品文档。
statement_history记录了执行时间超过阈值(log_min_duration_statement,默认3 s)的详细SQL信息,包含计划生成时间、执行时间、锁等待时间等信息,其中部分信息与参数track_stmt_stat_level设置的级别(默认为'OFF,L0')有关。 设置参数track_stmt_stat_level='OFF,L1'后,statement_history中可以记录计划信息、锁等待时间等信息。 必须在postgres库内查询,根据时间段查询慢SQL(按照执行时间排序)
SELECT *, finish_time - start_time as run_time FROM dbe_perf.statement_history WHERE start_time > '2022-07-08 18:00:00' AND start_time < '2022-07-08 19:00:00' -- 根据unique_query_id可以过滤出特定的查询 -- AND unique_query_id = 123456 ORDER BY run_time desc;
statement记录了SQL按照unique_sql_id归一化的执行信息,包括执行次数、总的执行时间、访问数据量、内存使用等信息。 根据unique_sql_id查询历史执行信息
SELECT *, total_elapse_time / n_calls as avg_elapse_time FROM dbe_perf.statement WHERE unique_query_id = 123456;
为了避免对生产环境产生影响,可以动态抓取SQL执行信息
-- 抓取指定unique_sql_id的全量SQL信息 -- 示例:unique_sql_id为3267119089,全量SQL级别为L2,相当于track_stmt_stat_level='L2,off' select * from dynamic_func_control('LOCAL', 'STMT', 'TRACK', '{"3267119089", "L2"}'); -- 打开之后,查询statement_history -- 关闭抓取,清理 select * from dynamic_func_control('LOCAL', 'STMT', 'UNTRACK', '{"3267119089"}'); select * from dynamic_func_control('LOCAL', 'STMT', 'LIST', '{}'); select * from dynamic_func_control('LOCAL', 'STMT', 'CLEAN', '{}');
SELECT * FROM dbe_perf.local_active_session WHERE query_start_time > '2022-07-08 18:00:00' AND query_start_time < '2022-07-08 19:00:00' AND unique_query ilike '%%';
根据查询结果中的pid和sessionid,使用函数中止查询
select pg_terminate_session(pid,sessionid);
查看统计信息
select * from pg_stats where tablename = '表名'; select * from pg_stats where tablename = '表名' and attname = '列名';
更新统计信息
analyze tablename;
手动设置列的distinct值(该字段不同值的数量,选择率 ~ 总行数/distinct值)
ALTER TABLE tablename ALTER COLUMN colname SET (n_distinct = 实际值); analyze tablename; -- analyze执行后生效 -- 取消设置 ALTER TABLE tablename ALTER COLUMN colname RESET (n_distinct); analyze tablename; -- analyze执行后生效
根据慢SQL分析结论,可以考虑修改GUC参数,但是修改参数同时也会影响其他查询的计划,属于高风险操作。
对于整体执行慢,可以通过分析WDR报告中TOP等待事件,进一步优化。