作为文章“
尝试为PostgreSQL创建ASH类似物”的简短补充。
挑战赛
您需要链接视图历史pg_stat_statemenets,pg_stat_activity。 结果,使用log_query服务表中的执行计划的历史记录,您可以获得许多有用的信息,可用于解决性能事件和优化查询。
警告
由于该主题的新颖性和不完整的测试期限,因此该文章可能包含错误。 强烈鼓励和期望批评和评论。
输入数据
History_pg_stat_activity表 pg_stat_db_queries表 CREATE TABLE pg_stat_db_queries ( database_id integer , queryid bigint , query text , max_time double precision );(
mvw_pg_stat_queries的实例化视图 CREATE MATERIALIZED VIEW public.mvw_pg_stat_queries AS SELECT t.queryid, t.max_time, t.query FROM public.dblink('LINK1'::text, 'SELECT queryid , max_time , query FROM pg_stat_statements WHERE dbid=(SELECT oid FROM pg_database WHERE datname=current_database() ) AND max_time >= 0 '::text) t(queryid bigint, max_time double precision, query text) WITH NO DATA;
Log_query表 CREATE TABLE log_query ( id integer , queryid bigint , query_md5hash text , database_id integer , timepoint timestamp without time zone , query text , explained_plan text[] , plan_md5hash text , explained_plan_wo_costs text[] , plan_hash_value text , ip text, port text , pid integer );
通用算法
刷新pg_stat_db_queries表
刷新材料视图mvw_pg_stat_queries CREATE OR REPLACE FUNCTION refresh_pg_stat_queries_list( database_id int) RETURNS BOOLEAN AS $$ DECLARE result BOOLEAN ; database_rec record ; BEGIN SELECT * INTO database_rec FROM endpoint e JOIN database d ON e.id = d.endpoint_id WHERE d.id = database_id ; IF NOT database_rec.is_need_monitoring THEN RAISE NOTICE 'NO NEED MONITORING FOR database_id=%',database_id; return TRUE ; END IF ; EXECUTE 'SELECT dblink_connect(''LINK1'',''host='||database_rec.host||' port=5432 dbname='||database_rec.name|| ' user='||database_rec.s_name||' password='||database_rec.s_pass|| ' '')'; REFRESH MATERIALIZED VIEW mvw_pg_stat_queries ; PERFORM dblink_disconnect('LINK1'); RETURN result; END $$ LANGUAGE plpgsql;
填充pg_stat_db_queries表 CREATE OR REPLACE FUNCTION refresh_pg_stat_db_queries( ) RETURNS BOOLEAN AS $$ DECLARE result BOOLEAN ; database_rec record ; pg_stat_rec record ; BEGIN TRUNCATE pg_stat_db_queries; FOR database_rec IN SELECT * FROM database d LOOP IF NOT database_rec.is_need_monitoring THEN RAISE NOTICE 'NO NEED MONITORING FOR database_id=%',database_rec.id; CONTINUE ; END IF ; PERFORM refresh_pg_stat_queries_list( database_rec.id ) ; FOR pg_stat_rec IN SELECT * FROM mvw_pg_stat_queries LOOP INSERT INTO pg_stat_db_queries ( database_id , queryid , query , max_time ) VALUES ( database_rec.id , pg_stat_rec.queryid , pg_stat_rec.query , pg_stat_rec.max_time); END LOOP; END LOOP; RETURN TRUE; END $$ LANGUAGE plpgsql;
结果,该表包含规范化查询文本queryid,当前时刻(用于监视)的最大查询执行时间。
填充log_query并形成执行计划的历史记录。
实际的请求文本取自日志文件。 从目标主机到监视主机的日志文件分为bash脚本,cron。 为了节省空间,并且由于在主机之间复制一个文本文件的任务很简单,因此未提供该脚本。
结果,该表包含实际的请求文本,执行计划,执行计划的哈希值,请求文本的哈希值。
在history_pg_stat_activity表中填写queryid值
update_history_pg_stat_activity_by_queryid.sql 结果,该表包含与查询的queryid值相对应的queryid值。
总结
通过链接pg_stat_activity,pg_stat_statements,log_query,您可以获得有关请求的许多有用信息,尤其是:
- 实施计划的历史。
- CPU时间请求的历史记录。
- 请求等待历史。
数据和许多其他报告将在下一篇文章中介绍。
发展历程
通过将可用信息与pg_locks视图的历史链接起来,可以获取有关请求正在等待哪个特定锁,最重要的是,哪个进程(请求)持有该锁的信息。
下一个文章将描述该问题的解决方案。 现在正在进行测试和改进。