ื ื™ืกื™ื•ืŸ ืœื™ืฆื•ืจ ืื ืœื•ื’ื™ ืฉืœ ASH ืขื‘ื•ืจ PostgreSQL

ื”ืฆื”ืจืช ื”ื‘ืขื™ื”

ื›ื“ื™ ืœื™ื™ืขืœ ืฉืื™ืœืชื•ืช PostgreSQL, ื ื“ืจืฉืช ืžืื•ื“ ื”ื™ื›ื•ืœืช ืœื ืชื— ื”ื™ืกื˜ื•ืจื™ื™ืช ืคืขื™ืœื•ืช, ื‘ืคืจื˜, ื”ืžืชื ื”, ื ืขื™ืœื•ืช ื•ืกื˜ื˜ื™ืกื˜ื™ืงื•ืช ื˜ื‘ืœื”.

ื”ื–ื“ืžื ื•ื™ื•ืช ื–ืžื™ื ื•ืช

ื›ืœื™ ื ื™ืชื•ื— ืขื•ืžืก ืขื‘ื•ื“ื” ื”ื™ืกื˜ื•ืจื™ ืื• "AWR for Postgres": ืคืชืจื•ืŸ ืžืื•ื“ ืžืขื ื™ื™ืŸ, ืื‘ืœ ืื™ืŸ ื”ื™ืกื˜ื•ืจื™ื” ืฉืœ pg_stat_activity ื•-pg_locks.

ืกื™ื•ืžืช pgsentinel :
ยซื›ืœ ื”ืžื™ื“ืข ื”ืžืฆื˜ื‘ืจ ืžืื•ื—ืกืŸ ืจืง ื‘-RAM, ื•ื›ืžื•ืช ื”ื–ื™ื›ืจื•ืŸ ื”ื ืฆืจื›ืช ืžื•ื•ืกืชืช ืขืœ ื™ื“ื™ ืžืกืคืจ ื”ืจืฉื•ืžื•ืช ื”ืื—ืจื•ื ื•ืช ื”ืžืื•ื—ืกื ื•ืช.

ื”ืฉื“ื” queryid ื ื•ืกืฃ - ืื•ืชื• queryid ืžื”ืกื™ื•ืžืช pg_stat_statements (ื ื“ืจืฉ ื”ืชืงื ื” ืžื•ืงื“ืžืช).ยซ

ื–ื”, ื›ืžื•ื‘ืŸ, ื™ืขื–ื•ืจ ืžืื•ื“, ืื‘ืœ ื”ื“ื‘ืจ ื”ืžื˜ืจื™ื“ ื‘ื™ื•ืชืจ ื”ื•ื ื”ื ืงื•ื“ื” ื”ืจืืฉื•ื ื”".ื›ืœ ื”ืžื™ื“ืข ื”ืžืฆื˜ื‘ืจ ืžืื•ื—ืกืŸ ืจืง ื‘-RAM ", ื›ืœื•ืžืจ. ื™ืฉ ื”ืฉืคืขื” ืขืœ ื‘ืกื™ืก ื”ื™ืขื“. ื‘ื ื•ืกืฃ, ืื™ืŸ ื”ื™ืกื˜ื•ืจื™ื™ืช ื ืขื™ืœื” ื•ืกื˜ื˜ื™ืกื˜ื™ืงื•ืช ื˜ื‘ืœื”. ื”ึธื”ึตืŸ. ื”ืคืชืจื•ืŸ ื‘ื“ืจืš ื›ืœืœ ืœื ืฉืœื: "ืื™ืŸ ืขื“ื™ื™ืŸ ื—ื‘ื™ืœื” ืžื•ื›ื ื” ืœื”ืชืงื ื”. ืžื•ืžืœืฅ ืœื”ื•ืจื™ื“ ืืช ื”ืžืงื•ืจื•ืช ื•ืœื”ืจื›ื™ื‘ ืืช ื”ืกืคืจื™ื™ื” ื‘ืขืฆืžืš. ืชื—ื™ืœื” ืขืœื™ืš ืœื”ืชืงื™ืŸ ืืช ื—ื‘ื™ืœืช "devel" ืขื‘ื•ืจ ื”ืฉืจืช ืฉืœืš ื•ืœื”ื’ื“ื™ืจ ืืช ื”ื ืชื™ื‘ ืœ-pg_config ื‘ืžืฉืชื ื” PATH.".

ื‘ืื•ืคืŸ ื›ืœืœื™, ื™ืฉ ื”ืจื‘ื” ืžื”ื•ืžื”, ื•ื‘ืžืงืจื” ืฉืœ ืžืกื“ื™ ื ืชื•ื ื™ื ืจืฆื™ื ื™ื™ื ืฉืœ ื™ื™ืฆื•ืจ, ื™ื™ืชื›ืŸ ืฉืœื ื ื™ืชืŸ ืœืขืฉื•ืช ืฉื•ื ื“ื‘ืจ ืขื ื”ืฉืจืช. ืื ื—ื ื• ืฆืจื™ื›ื™ื ืœื”ืžืฆื™ื ืžืฉื”ื• ืžืฉืœื ื• ืฉื•ื‘.

ืื–ื”ืจื”

ื‘ืฉืœ ื”ื ืคื— ื”ื’ื“ื•ืœ ืœืžื“ื™ ื•ื‘ืฉืœ ืชืงื•ืคืช ื”ื‘ื“ื™ืงื•ืช ื”ืœื ืžืœืื”, ื”ืžืืžืจ ื”ื•ื ื‘ืขื™ืงืจ ื‘ืขืœ ืื•ืคื™ ืื™ื ืคื•ืจืžื˜ื™ื‘ื™, ืืœื ื›ืžืขืจื›ืช ืฉืœ ืชื–ื•ืช ื•ืชื•ืฆืื•ืช ื‘ื™ื ื™ื™ื.
ื—ื•ืžืจ ืžืคื•ืจื˜ ื™ื•ืชืจ ื™ื•ื›ืŸ ื‘ื”ืžืฉืš, ื‘ื—ืœืงื™ื

ื˜ื™ื•ื˜ืช ื“ืจื™ืฉื•ืช ืœืคืชืจื•ืŸ

ื™ืฉ ืฆื•ืจืš ืœืคืชื— ื›ืœื™ ื”ืžืืคืฉืจ ืœืš ืœืื—ืกืŸ:

pg_stat_activity ืชืฆื•ื’ืช ื”ื™ืกื˜ื•ืจื™ื™ืช
ื”ื™ืกื˜ื•ืจื™ื™ืช ื ืขื™ืœืช ื”ืคืขืœื” ื‘ืืžืฆืขื•ืช ืชืฆื•ื’ืช pg_locks

ื“ืจื™ืฉืช ืคืชืจื•ืŸ-ืœืžื–ืขืจ ืืช ื”ื”ืฉืคืขื” ืขืœ ืžืกื“ ื”ื ืชื•ื ื™ื ื”ื™ืขื“.

ืจืขื™ื•ืŸ ื›ืœืœื™โ€“ ืกื•ื›ืŸ ืื™ืกื•ืฃ ื”ื ืชื•ื ื™ื ืžื•ืคืขืœ ืœื ื‘ืžืกื“ ื”ื ืชื•ื ื™ื ื”ื™ืขื“, ืืœื ื‘ืžืกื“ ื”ื ืชื•ื ื™ื ื”ื ื™ื˜ื•ืจ ื›ืฉื™ืจื•ืช ืžืขืจื›ืชื™. ื›ืŸ, ื™ื™ืชื›ืŸ ืื•ื‘ื“ืŸ ื ืชื•ื ื™ื ืžืกื•ื™ื, ืื‘ืœ ื–ื” ืœื ืงืจื™ื˜ื™ ืœื“ื™ื•ื•ื—, ืื‘ืœ ืื™ืŸ ื”ืฉืคืขื” ืขืœ ืžืกื“ ื”ื ืชื•ื ื™ื ืฉืœ ื”ื™ืขื“ ืžื‘ื—ื™ื ืช ื–ื™ื›ืจื•ืŸ ื•ืฉื˜ื— ื“ื™ืกืง. ื•ื‘ืžืงืจื” ืฉืœ ืฉื™ืžื•ืฉ ื‘ืžืื’ืจ ื—ื™ื‘ื•ืจื™ื, ื”ื”ืฉืคืขื” ืขืœ ืชื”ืœื™ื›ื™ ื”ืžืฉืชืžืฉ ื”ื™ื ืžื™ื ื™ืžืœื™ืช.

ืฉืœื‘ื™ ื™ื™ืฉื•ื

1. ืฉื•ืœื—ื ื•ืช ืฉื™ืจื•ืช

ืกื›ื™ืžื” ื ืคืจื“ืช ืžืฉืžืฉืช ืœืื—ืกื•ืŸ ื˜ื‘ืœืื•ืช, ื›ื“ื™ ืœื ืœืกื‘ืš ืืช ื”ื ื™ืชื•ื— ืฉืœ ื”ื˜ื‘ืœืื•ืช ื”ืขื™ืงืจื™ื•ืช ื‘ื”ืŸ ื ืขืฉื” ืฉื™ืžื•ืฉ.

DROP SCHEMA IF EXISTS activity_hist ;
CREATE SCHEMA activity_hist AUTHORIZATION monitor ;

ื—ืฉื•ื‘: ื”ืกื›ื™ืžื” ืœื ื ื•ืฆืจืช ื‘ืžืกื“ ื”ื ืชื•ื ื™ื ื”ื™ืขื“, ืืœื ื‘ืžืกื“ ื”ื ืชื•ื ื™ื ื”ื ื™ื˜ื•ืจ.

pg_stat_activity ืชืฆื•ื’ืช ื”ื™ืกื˜ื•ืจื™ื™ืช

ื˜ื‘ืœื” ืžืฉืžืฉืช ืœืื—ืกื•ืŸ ืฆื™ืœื•ืžื™ ืžืฆื‘ ื ื•ื›ื—ื™ื™ื ืฉืœ ืชืฆื•ื’ืช pg_stat_activity

activity_hist.history_pg_stat_activity :

--ACTIVITY_HIST.HISTORY_PG_STAT_ACTIVITY
DROP TABLE IF EXISTS activity_hist.history_pg_stat_activity;
CREATE TABLE activity_hist.history_pg_stat_activity
(
  timepoint timestamp without time zone ,
  datid             oid  , 
  datname           name ,
  pid               integer,
  usesysid          oid    ,
  usename           name   ,
  application_name  text   ,
  client_addr       inet   ,
  client_hostname   text   ,
  client_port       integer,
  backend_start     timestamp with time zone ,
  xact_start        timestamp with time zone ,
  query_start       timestamp with time zone ,
  state_change      timestamp with time zone ,
  wait_event_type   text ,                     
  wait_event        text ,                   
  state             text ,                  
  backend_xid       xid  ,                 
  backend_xmin      xid  ,                
  query             text ,               
  backend_type      text ,  
  queryid           bigint
);

ื›ื“ื™ ืœื–ืจื– ืืช ื”ื”ื›ื ืกื” - ืœืœื ืื™ื ื“ืงืกื™ื ืื• ื”ื’ื‘ืœื•ืช.

ื›ื“ื™ ืœืื—ืกืŸ ืืช ื”ื”ื™ืกื˜ื•ืจื™ื” ืขืฆืžื”, ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘ื˜ื‘ืœื” ืžื—ื•ืœืงืช:

activity_hist.archive_pg_stat_activity :

DROP TABLE IF EXISTS activity_hist.archive_pg_stat_activity;
CREATE TABLE activity_hist.archive_pg_stat_activity
(
  timepoint timestamp without time zone ,
  datid             oid  , 
  datname           name ,
  pid               integer,
  usesysid          oid    ,
  usename           name   ,
  application_name  text   ,
  client_addr       inet   ,
  client_hostname   text   ,
  client_port       integer,
  backend_start     timestamp with time zone ,
  xact_start        timestamp with time zone ,
  query_start       timestamp with time zone ,
  state_change      timestamp with time zone ,
  wait_event_type   text ,                     
  wait_event        text ,                   
  state             text ,                  
  backend_xid       xid  ,                 
  backend_xmin      xid  ,                
  query             text ,               
  backend_type      text ,
  queryid           bigint
)
PARTITION BY RANGE (timepoint);

ืžื›ื™ื•ื•ืŸ ืฉื‘ืžืงืจื” ื–ื” ืื™ืŸ ื“ืจื™ืฉื•ืช ืœืžื”ื™ืจื•ืช ื”ื›ื ืกื”, ื ื•ืฆืจื• ื›ืžื” ืื™ื ื“ืงืกื™ื ื›ื“ื™ ืœื”ืื™ืฅ ืืช ื™ืฆื™ืจืช ื”ื“ื•ื—ื•ืช.

ื”ื™ืกื˜ื•ืจื™ื™ืช ื—ืกื™ืžืช ื”ืคืขืœื”

ื˜ื‘ืœื” ืžืฉืžืฉืช ืœืื—ืกื•ืŸ ืชืžื•ื ื•ืช ืžืฆื‘ ื ื•ื›ื—ื™ื•ืช ืฉืœ ื ืขื™ืœื•ืช ื”ืคืขืœื”:

activity_hist.history_locking :

--ACTIVITY_HIST.HISTORY_LOCKING
DROP TABLE IF EXISTS activity_hist.history_locking;
CREATE TABLE activity_hist.history_locking
(
	timepoint timestamp without time zone ,
	locktype text ,
	relation oid ,
	mode text ,
	tid xid ,
	vtid text ,
	pid integer ,
	blocking_pids integer[] ,
	granted boolean
);

ื›ืžื• ื›ืŸ, ื›ื“ื™ ืœื”ืื™ืฅ ืืช ื”ื”ื›ื ืกื”, ืื™ืŸ ืื™ื ื“ืงืกื™ื ืื• ื”ื’ื‘ืœื•ืช.

ื›ื“ื™ ืœืื—ืกืŸ ืืช ื”ื”ื™ืกื˜ื•ืจื™ื” ืขืฆืžื”, ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘ื˜ื‘ืœื” ืžื—ื•ืœืงืช:

activity_hist.archive_locking:

DROP TABLE IF EXISTS activity_hist.archive_locking;
CREATE TABLE activity_hist.archive_locking
(
	timepoint timestamp without time zone ,
	locktype text ,
	relation oid ,
	mode text ,
	tid xid ,
	vtid text ,
	pid integer ,
	blocking_pids integer[] ,
	granted boolean	
)
PARTITION BY RANGE (timepoint);

ืžื›ื™ื•ื•ืŸ ืฉื‘ืžืงืจื” ื–ื” ืื™ืŸ ื“ืจื™ืฉื•ืช ืœืžื”ื™ืจื•ืช ื”ื›ื ืกื”, ื ื•ืฆืจื• ื›ืžื” ืื™ื ื“ืงืกื™ื ื›ื“ื™ ืœื”ืื™ืฅ ืืช ื™ืฆื™ืจืช ื”ื“ื•ื—ื•ืช.

2. ืžื™ืœื•ื™ ื”ื”ื™ืกื˜ื•ืจื™ื” ื”ื ื•ื›ื—ื™ืช

ื›ื“ื™ ืœืืกื•ืฃ ื™ืฉื™ืจื•ืช ืชืฆืœื•ืžื™ ืชืฆื•ื’ื”, ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘ืกืงืจื™ืคื˜ bash ื”ืžืจื™ืฅ ืืช ื”ืคื•ื ืงืฆื™ื” plpgsql.

get_current_activity.sh

#!/bin/bash
#########################################################
#get_current_activity.sh

ERROR_FILE='/home/demon/get_current_activity'$(date +%Y%m%d-)'T'$(date +%H)$(date +%M)$(date +%S)
host=$1
s_name=$2
s_pass=$3

psql  -A -t -q -v ON_ERROR_STOP=1 -c "SELECT activity_hist.get_current_activity( '$host' , '$s_name' , '$s_pass' )" >/dev/null 2>$ERROR_FILE

line_count=`cat $ERROR_FILE | wc -l`
if [[ $line_count != '0' ]];
then
    rm -f /home/demon/*.err >/dev/null 2>/dev/null
	cp $ERROR_FILE $ERROR_FILE'.err' >/dev/null 2>/dev/null  
fi
rm $ERROR_FILE >/dev/null 2>/dev/null
exit 0

plpgsql ื”ืคื•ื ืงืฆื™ื” dblink ื ื™ื’ืฉืช ืœืชืฆื•ื’ื•ืช ื‘ืžืกื“ ื”ื ืชื•ื ื™ื ื”ื™ืขื“ ื•ืžื›ื ื™ืกื” ืฉื•ืจื•ืช ืœื˜ื‘ืœืื•ืช ืฉื™ืจื•ืช ื‘ืžืกื“ ื”ื ืชื•ื ื™ื ื”ื ื™ื˜ื•ืจ.

get_current_activity.sql

CREATE OR REPLACE FUNCTION activity_hist.get_current_activity( current_host text , current_s_name text , current_s_pass text ) RETURNS BOOLEAN AS $$
DECLARE 
  database_rec record;
  dblink_str text ;
BEGIN   

	EXECUTE 'SELECT dblink_connect(''LINK1'',''host='||current_host||' port=5432 dbname=postgres'||
	                                         ' user='||current_s_name||' password='||current_s_pass|| ' '')';



--------------------------------------------------------------------
--GET pg_stat_activity stats
	INSERT INTO activity_hist.history_pg_stat_activity
	(
		SELECT * FROM dblink('LINK1',
			'SELECT 
			now() , 
			datid             , 
			datname           ,
			pid               ,
			usesysid              ,
			usename              ,
			application_name     ,
			client_addr          ,
			client_hostname      ,
			client_port       ,
			backend_start         ,
			xact_start            ,
			query_start           ,
			state_change          ,
			wait_event_type    ,                     
			wait_event         ,                   
			state              ,                  
			backend_xid         ,                 
			backend_xmin        ,                
			query              ,               
			backend_type   			
		FROM pg_stat_activity
		') 
		AS t (
		    timepoint 		  timestamp without time zone ,			
			datid             oid  , 
			datname           name ,
			pid               integer,
			usesysid          oid    ,
			usename           name   ,
			application_name  text   ,
			client_addr       inet   ,
			client_hostname   text   ,
			client_port       integer,
			backend_start     timestamp with time zone ,
			xact_start        timestamp with time zone ,
			query_start       timestamp with time zone ,
			state_change      timestamp with time zone ,
			wait_event_type   text ,                     
			wait_event        text ,                   
			state             text ,                  
			backend_xid       xid  ,                 
			backend_xmin      xid  ,                
			query             text ,               
			backend_type      text 			
		)
	);

---------------------------------------	
--ACTIVITY_HIST.HISTORY_LOCKING	
	INSERT INTO activity_hist.history_locking
	(
		SELECT * FROM dblink('LINK1',
			'SELECT 
			now() , 
			lock.locktype,
			lock.relation,
			lock.mode,
			lock.transactionid as tid,
			lock.virtualtransaction as vtid,
			lock.pid,
			pg_blocking_pids(lock.pid), 
			lock.granted
			FROM 	pg_catalog.pg_locks lock LEFT JOIN pg_catalog.pg_database db ON db.oid = lock.database
			WHERE NOT lock.pid = pg_backend_pid()	
		') 
		AS t (
			timepoint timestamp without time zone ,
			locktype text ,
			relation oid , 
			mode text ,
			tid xid ,
			vtid text ,
			pid integer ,
			blocking_pids integer[] ,
			granted boolean
		)
	);
	PERFORM dblink_disconnect('LINK1');
	
	RETURN TRUE ;
END
$$ LANGUAGE plpgsql;

ื›ื“ื™ ืœืืกื•ืฃ ืชืžื•ื ื•ืช ืžืฆื‘ ืฉืœ ืฆืคื™ื™ื”, ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘ืฉื™ืจื•ืช systemd ื•ื‘ืฉื ื™ ืกืงืจื™ืคื˜ื™ื:

pg_current_activity.service

# /etc/systemd/system/pg_current_activity.service
[Unit]
Description=Collect history of pg_stat_activity , pg_locks 
Wants=pg_current_activity.timer

[Service]
Type=forking
StartLimitIntervalSec=0
ExecStart=/home/postgres/pgutils/demon/get_current_activity.sh 10.124.70.40 postgres postgres

[Install]
WantedBy=multi-user.target

pg_current_activity.timer

# /etc/systemd/system/pg_current_activity.timer
[Unit]
Description=Run pg_current_activity.sh every 1 second
Requires=pg_current_activity.service

[Timer]
Unit=pg_current_activity.service
OnCalendar=*:*:0/1
AccuracySec=1

[Install]
WantedBy=timers.target

ื”ืงืฆื” ื–ื›ื•ื™ื•ืช ืœืชืกืจื™ื˜ื™ื:
# chmod 755 pg_current_activity.timer
# chmod 755 pg_current_activity.service

ื‘ื•ืื• ื ืชื—ื™ืœ ืืช ื”ืฉื™ืจื•ืช:
# systemctl daemon-ืœื˜ืขื•ืŸ ืžื—ื“ืฉ
# systemctl ื”ืชื—ืœ ืืช pg_current_activity.service

ืœืคื™ื›ืš, ื”ื”ื™ืกื˜ื•ืจื™ื” ืฉืœ ื”ืฆืคื™ื•ืช ื ืืกืคืช ื‘ืฆื•ืจื” ืฉืœ ืชืฆืœื•ืžื™ื ืฉื ื™ื™ื” ืื—ืจ ืฉื ื™ื™ื”. ื›ืžื•ื‘ืŸ ืฉืื ื”ื›ืœ ื™ื™ืฉืืจ ื›ืžื• ืฉื”ื•ื, ื”ืฉื•ืœื—ื ื•ืช ื™ื’ื“ืœื• ืžื”ืจ ืžืื•ื“ ื‘ื’ื•ื“ืœื ื•ืขื‘ื•ื“ื” ืคืจื•ื“ื•ืงื˜ื™ื‘ื™ืช ืคื—ื•ืช ืื• ื™ื•ืชืจ ืชื”ืคื•ืš ืœื‘ืœืชื™ ืืคืฉืจื™ืช.

ื™ืฉ ืฆื•ืจืš ืœืืจื’ืŸ ืืจื›ื™ื•ืŸ ื ืชื•ื ื™ื.

3. ื”ื™ืกื˜ื•ืจื™ื™ืช ืืจื›ื™ื•ืŸ

ืขื‘ื•ืจ ืืจื›ื™ื•ืŸ, ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘ืืจื›ื™ื•ืŸ ืฉืœ ื˜ื‘ืœืื•ืช ืžื—ื•ืœืงื•ืช*.

ืžื—ื™ืฆื•ืช ื—ื“ืฉื•ืช ื ื•ืฆืจื•ืช ื›ืœ ืฉืขื”, ื‘ืขื•ื“ ื ืชื•ื ื™ื ื™ืฉื ื™ื ืžื•ืกืจื™ื ืžื˜ื‘ืœืื•ืช ื”ื”ื™ืกื˜ื•ืจื™ื”*, ื›ืš ืฉื’ื•ื“ืœ ื˜ื‘ืœืื•ืช ื”ื”ื™ืกื˜ื•ืจื™ื”* ืœื ืžืฉืชื ื” ื”ืจื‘ื” ื•ืžื”ื™ืจื•ืช ื”ื”ื›ื ืกื” ืœื ื™ื•ืจื“ืช ืขื ื”ื–ืžืŸ.

ื™ืฆื™ืจืช ืงื˜ืขื™ื ื—ื“ืฉื™ื ืžืชื‘ืฆืขืช ืขืœ ื™ื“ื™ ื”ืคื•ื ืงืฆื™ื” plpgsql activity_hist.archive_current_activity. ื”ืืœื’ื•ืจื™ืชื ืฉืœ ื”ืขื‘ื•ื“ื” ืคืฉื•ื˜ ืžืื•ื“ (ื‘ืืžืฆืขื•ืช ื”ื“ื•ื’ืžื” ืฉืœ ื”ืกืขื™ืฃ ืœื˜ื‘ืœืช archive_pg_stat_activity).

ืฆื•ืจ ื•ืžืœื ืงื˜ืข ื—ื“ืฉ

EXECUTE format(
'CREATE TABLE ' || partition_name || 
' PARTITION OF activity_hist.archive_pg_stat_activity FOR VALUES FROM ( %L ) TO ( %L ) ' , 
to_char(date_trunc('year', partition_min_range ),'YYYY')||'-'||
to_char(date_trunc('month', partition_min_range ),'MM')||'-'||
to_char(date_trunc('day', partition_min_range ),'DD')||' '||
to_char(date_trunc('hour', partition_min_range ),'HH24')||':00', 
to_char(date_trunc('year', partition_max_range ),'YYYY')||'-'||
to_char(date_trunc('month', partition_max_range ),'MM')||'-'||
to_char(date_trunc('day', partition_max_range ),'DD')||' '||
to_char(date_trunc('hour', partition_max_range ),'HH24')||':00'
);

INSERT INTO activity_hist.archive_pg_stat_activity
(
	SELECT 	* 
	FROM 	activity_hist.history_pg_stat_activity
	WHERE 	timepoint BETWEEN partition_min_range AND partition_max_range 		
);

ื™ืฆื™ืจืช ืื™ื ื“ืงืกื™ื

EXECUTE format	(
'CREATE INDEX '||index_name||
' ON '||partition_name||' ( wait_event_type , backend_type , timepoint )' 
);

EXECUTE format	('CREATE INDEX '||index_name||
' ON '||partition_name||' ( wait_event_type , backend_type , timepoint , queryid )' 
);

ื”ืกืจืช ื ืชื•ื ื™ื ื™ืฉื ื™ื ืžื˜ื‘ืœืช history_pg_stat_activity

DELETE 
FROM 	activity_hist.history_pg_stat_activity
WHERE 	timepoint < partition_max_range;

ื›ืžื•ื‘ืŸ ืฉืžื“ื™ ืคืขื ืงื˜ืขื™ื ื™ืฉื ื™ื ื ืžื—ืงื™ื ื›ืžื™ื•ืชืจื™ื.

ื“ื•ื—ื•ืช ื‘ืกื™ืกื™ื™ื

ื‘ืขืฆื, ืœืžื” ื›ืœ ื–ื” ื ืขืฉื”? ืœื”ืฉื™ื’ ื“ื•ื—ื•ืช ืฉืžื–ื›ื™ืจื™ื ื‘ืฆื•ืจื” ืžืื•ื“ ืžืขื•ืจืคืœืช ืืช ื”-AWR ืฉืœ ืื•ืจืงืœ.

ื—ืฉื•ื‘ ืœื”ื•ืกื™ืฃ ืฉื›ื“ื™ ืœืงื‘ืœ ื“ื•ื—ื•ืช ืฆืจื™ืš ืœื‘ื ื•ืช ื—ื™ื‘ื•ืจ ื‘ื™ืŸ ื”ืชืฆื•ื’ื•ืช pg_stat_activity ื•-pg_stat_statements. ื”ื˜ื‘ืœืื•ืช ืžืงื•ืฉืจื•ืช ืขืœ ื™ื“ื™ ื”ื•ืกืคืช ืขืžื•ื“ืช 'queryid' ืœื˜ื‘ืœืื•ืช 'history_pg_stat_activity', 'archive_pg_stat_activity'. ื”ืฉื™ื˜ื” ืฉืœ โ€‹โ€‹ื”ื•ืกืคืช ืขืจืš ืขืžื•ื“ื” ื”ื™ื ืžืขื‘ืจ ืœื”ื™ืงืฃ ืฉืœ ืžืืžืจ ื–ื” ื•ืžืชื•ืืจืช ื›ืืŸ - pg_stat_statements + pg_stat_activity + loq_query = pg_ash? .

ื–ืžืŸ ืžืขื‘ื“ ื›ื•ืœืœ ืœืฉืื™ืœืชื•ืช

ื‘ืงืฉื”:

WITH hist AS
(
SELECT 
	aa.query ,aa.queryid ,			
	count(*) * interval '1 second' AS duration 
FROM 	activity_hist.archive_pg_stat_activity aa
WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND  pg_stat_history_end+(current_hour_diff * interval '1 hour')  AND backend_type = 'client backend' AND datname != 'postgres' AND	( aa.wait_event_type IS NULL  ) ANDaa.state = 'active'
GROUP BY aa.wait_event_type , aa.wait_event , aa.query ,aa.queryid		
UNION 
SELECT 
	ha.query ,ha.queryid,
	count(*) * interval '1 second' AS duration 
FROM 	activity_hist.history_pg_stat_activity_for_reports ha
WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour')  AND 	backend_type = 'client backend' AND datname != 'postgres' AND ( ha.wait_event_type IS NULL  )AND ha.state = 'active'
GROUP BY ha.wait_event_type , ha.wait_event , ha.query ,ha.queryid		
)
SELECT 	query , queryid , SUM( duration ) as duration 
FROM hist
GROUP BY  query , queryid 
ORDER BY 3 DESC

ืœื“ื•ื’ืžื”:

-------------------------------------------------------------------
| TOTAL CPU TIME FOR QUERIES : 07:47:36
+----+----------------------------------------+--------------------
|   #|                                 queryid|            duration
+----+----------------------------------------+--------------------
|   1|                      389015618226997618|            04:28:58
|   2|                                        |            01:07:29
|   3|                     1237430309438971376|            00:59:38
|   4|                     4710212362688288619|            00:50:48
|   5|                       28942442626229688|            00:15:50
|   6|                     9150846928388977274|            00:04:46
|   7|                    -6572922443698419129|            00:00:06
|   8|                                        |            00:00:01
+----+----------------------------------------+--------------------

ื–ืžืŸ ื”ืžืชื ื” ื›ื•ืœืœ ืœืฉืื™ืœืชื•ืช

ื‘ืงืฉื”:

WITH hist AS
(
SELECT 
	aa.query ,aa.queryid ,			
	count(*) * interval '1 second' AS duration 
FROM 	activity_hist.archive_pg_stat_activity aa
WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour')  AND 
	backend_type = 'client backend' AND datname != 'postgres' AND
	( aa.wait_event_type IS NOT NULL  ) 
GROUP BY aa.wait_event_type , aa.wait_event , aa.query ,aa.queryid		
UNION 
SELECT 
	ha.query ,ha.queryid,
	count(*) * interval '1 second' AS duration 
FROM 	activity_hist.history_pg_stat_activity_for_reports ha
WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour')  AND 
	backend_type = 'client backend' AND datname != 'postgres' AND				
	( ha.wait_event_type IS NOT NULL  )
GROUP BY ha.wait_event_type , ha.wait_event , ha.query ,ha.queryid		
)
SELECT 	query , queryid , SUM( duration ) as duration 
FROM hist
GROUP BY  query , queryid 
ORDER BY 3 DESC 

ืœื“ื•ื’ืžื:

-------------------------------------------------------------------
| TOTAL WAITINGS TIME FOR QUERIES : 21:55:04
+----+----------------------------------------+--------------------
|   #|                                 queryid|            duration
+----+----------------------------------------+--------------------
|   1|                      389015618226997618|            16:19:05
|   2|                                        |            03:47:04
|   3|                     8085340880788646241|            00:40:20
|   4|                     4710212362688288619|            00:13:35
|   5|                     9150846928388977274|            00:12:25
|   6|                       28942442626229688|            00:11:32
|   7|                     1237430309438971376|            00:09:45
|   8|                     2649515222348904837|            00:09:37
|   9|                                        |            00:03:45
|  10|                     3167065002719415275|            00:02:20
|  11|                     5731212217001535134|            00:02:13
|  12|                     8304755792398128062|            00:01:31
|  13|                     2649515222348904837|            00:00:59
|  14|                     2649515222348904837|            00:00:22
|  15|                                        |            00:00:12
|  16|                     3422818749220588372|            00:00:08
|  17|                    -5730801771815999400|            00:00:03
|  18|                    -1473395109729441239|            00:00:02
|  19|                     2404820632950544954|            00:00:02
|  20|                    -6572922443698419129|            00:00:02
|  21|                     2369289265278398647|            00:00:01
|  22|                      180077086776069052|            00:00:01
+----+----------------------------------------+--------------------

ืžืžืชื™ื ื™ื ืœืฉืื™ืœืชื•ืช

ื‘ืงืฉื•ืช:

WITH hist AS
(
SELECT 
	aa.wait_event_type , aa.wait_event 
FROM 	activity_hist.archive_pg_stat_activity aa
WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND 
	backend_type = 'client backend' AND datname != 'postgres' AND
	aa.wait_event IS NOT NULL 
GROUP BY aa.wait_event_type , aa.wait_event
UNION 
SELECT 
	ha.wait_event_type , ha.wait_event 
FROM 	activity_hist.history_pg_stat_activity_for_reports ha
WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND 
	backend_type = 'client backend' AND datname != 'postgres' AND
	ha.wait_event IS NOT NULL 
GROUP BY ha.wait_event_type , ha.wait_event		
)
SELECT 	wait_event_type , wait_event 
FROM hist
GROUP BY wait_event_type , wait_event
ORDER BY 1 ASC,2 ASC

----------------------------------------------------------------------

WITH hist AS
(
SELECT 
	aa.wait_event_type , aa.wait_event , aa.query ,aa.queryid ,			
	count(*) * interval '1 second' AS duration 
FROM 	activity_hist.archive_pg_stat_activity aa
WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND 
	backend_type = 'client backend' AND datname != 'postgres' AND
	( aa.wait_event_type = waitings_stat_rec.wait_event_type AND aa.wait_event = waitings_stat_rec.wait_event )
GROUP BY aa.wait_event_type , aa.wait_event , aa.query ,aa.queryid		
UNION 
SELECT 
	ha.wait_event_type , ha.wait_event , ha.query ,ha.queryid,
	count(*) * interval '1 second' AS duration 
FROM 	activity_hist.history_pg_stat_activity_for_reports ha
WHERE timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND 
	backend_type = 'client backend' AND datname != 'postgres' AND				
	( ha.wait_event_type = waitings_stat_rec.wait_event_type AND ha.wait_event = waitings_stat_rec.wait_event )
GROUP BY ha.wait_event_type , ha.wait_event , ha.query ,ha.queryid		
)
SELECT 	query , queryid , SUM( duration ) as duration 
FROM hist
GROUP BY  query , queryid 
ORDER BY 3 DESC

ืœื“ื•ื’ืžื”:

------------------------------------------------
| WAITINGS FOR QUERIES
+-----------------------------------------------
|                      wait_event_type = Client|
|                       wait_event = ClientRead|
|                        Total time  = 00:46:56|
------------------------------------------------
|    #|             queryid|            duration
+-----+--------------------+--------------------
|    1| 8085340880788646241|            00:40:20
|    2|                    |            00:03:45
|    3| 5731212217001535134|            00:01:53
|    4|                    |            00:00:12
|    5| 9150846928388977274|            00:00:09
|    6| 3422818749220588372|            00:00:08
|    7| 1237430309438971376|            00:00:06
|    8|   28942442626229688|            00:00:05
|    9| 4710212362688288619|            00:00:05
|   10|-5730801771815999400|            00:00:03
|   11| 8304755792398128062|            00:00:02
|   12|-6572922443698419129|            00:00:02
|   13|-1473395109729441239|            00:00:02
|   14| 2404820632950544954|            00:00:02
|   15|  180077086776069052|            00:00:01
|   16| 2369289265278398647|            00:00:01

+-----------------------------------------------
|                          wait_event_type = IO|
|                      wait_event = BufFileRead|
|                        Total time  = 00:00:38|
------------------------------------------------
|    #|             queryid|            duration
+-----+--------------------+--------------------
|    1|   28942442626229688|            00:00:38

+-----------------------------------------------

ื”ื™ืกื˜ื•ืจื™ื™ืช ืชื”ืœื™ื›ื™ื ื ืขื•ืœื™ื

ื‘ึผึทืงึธืฉืึธื”:

SELECT 
MIN(date_trunc('second',timepoint)) AS started , 
	count(*) * interval '1 second' as duration ,
	pid , blocking_pids , relation , mode , locktype 	 
FROM 
	activity_hist.archive_locking al 
WHERE 
	timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND
	NOT granted AND 
	locktype = 'relation' 
GROUP BY pid , blocking_pids , relation , mode , locktype			
UNION
SELECT 
	MIN(date_trunc('second',timepoint)) AS started , 
	count(*) * interval '1 second' as duration ,
	pid , blocking_pids , relation , mode , locktype
FROM 
	activity_hist.history_locking 
WHERE 
	timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND
	NOT granted AND 
	locktype = 'relation' 
GROUP BY pid , blocking_pids , relation , mode , locktype			
ORDER BY 1

ืœื“ื•ื’ืžื”:

-------------------------------------------------- -------------------------------------------------- ---------------------------------- | ื”ื™ืกื˜ื•ืจื™ื™ืช ืชื”ืœื™ื›ื™ื ื ืขื•ืœื™ื +-------------------+-------- --+------ ----------------------------+-------------------- +------------------------ | #| pid| ื”ืชื—ื™ืœ| ืžืฉืš| blocking_pids| ืงืฉืจ| ืžืฆื‘| ืกื•ื’ ืžื ืขื•ืœ +-----------+-----------+-----+----------+-------- --------------+------------+-----------------------+----- -------------- | 1| 26224| 2019-09-02 19:32:16| 00:01:45| {26211}| 16541| AccessShareLock| ืงืฉืจ | 2| 26390| 2019-09-02 19:34:03| 00:00:53| {26211}| 16541| AccessShareLock| ืงืฉืจ | 3| 26391| 2019-09-02 19:34:03| 00:00:53| {26211}| 16541| AccessShareLock| ืงืฉืจ | 4| 26531| 2019-09-02 19:35:27| 00:00:12| {26211}| 16541| AccessShareLock| ืงืฉืจ | 5| 27284| 2019-09-02 19:44:02| 00:00:19| {27276}| 16541| AccessShareLock| ืงืฉืจ | 6| 27283| 2019-09-02 19:44:02| 00:00:19| {27276}| 16541| AccessShareLock| ืงืฉืจ | 7| 27286| 2019-09-02 19:44:02| 00:00:19| {27276}| 16541| AccessShareLock| ืงืฉืจ | 8| 27423| 2019-09-02 19:45:24| 00:00:12| {27394}| 16541| AccessShareLock| ืงืฉืจ | 9| 27648| 2019-09-02 19:48:06| 00:00:20| {27647}| 16541| AccessShareLock| ืงืฉืจ | 10| 27650| 2019-09-02 19:48:06| 00:00:20| {27647}| 16541| AccessShareLock| ืงืฉืจ | 11| 27735| 2019-09-02 19:49:08| 00:00:06| {27650}| 16541| AccessExclusiveLock| ืงืฉืจ | 12| 28380| 2019-09-02 19:56:03| 00:01:56| {28379}| 16541| AccessShareLock| ืงืฉืจ | 13| 28379| 2019-09-02 19:56:03| 00:00:01| 28377| 16541| AccessExclusiveLock| ืงืฉืจ | | | | | 28376| | 

ื”ื™ืกื˜ื•ืจื™ื™ืช ืชื”ืœื™ื›ื™ ื—ืกื™ืžื”

ื‘ืงืฉื•ืช:

SELECT 
blocking_pids 
FROM 
	activity_hist.archive_locking al 
WHERE 
	timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND
	NOT granted AND 
	locktype = 'relation' 
GROUP BY blocking_pids 		
UNION
SELECT 
	blocking_pids 
FROM 
	activity_hist.history_locking 
WHERE 
	timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND
	NOT granted AND 
	locktype = 'relation' 
GROUP BY blocking_pids 		
ORDER BY 1

---------------------------------------------------------------

SELECT 
	pid , usename , application_name , datname ,
	MIN(date_trunc('second',timepoint)) as started , 
	count(*) * interval '1 second' as duration ,		 
	state , 
	query
				FROM  	activity_hist.archive_pg_stat_activity
				WHERE 	pid= current_pid AND 
						timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') 						 
				GROUP BY pid , usename , application_name , 
						datname , 
						state_change, 
						state , 
						query 
				UNION
				SELECT 
					pid , usename , application_name , datname ,
					MIN(date_trunc('second',timepoint)) as started , 
					count(*) * interval '1 second' as duration ,		 
					state , 
					query
				FROM  	activity_hist.history_pg_stat_activity_for_reports
				WHERE 	pid= current_pid AND 
						timepoint BETWEEN pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') 						 
				GROUP BY pid , usename , application_name , 
						datname , 
						state_change, 
						state , 
						query 
				ORDER BY 5 , 1

ืœื“ื•ื’ืžื”:

-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ----------------------- ื”ื™ืกื˜ื•ืจื™ื™ืช ืชื”ืœื™ื›ื™ ื—ืกื™ืžื” +------------------ ---+---------------------+-----------+--------------------- ------+---------------------+--------- -------+----------------------------------------------- | #| pid| ืฉื ืฉื™ืžื•ืฉ| ืฉื_ื™ื™ืฉื•ื| ืฉื ื ืชื•ื ื™ื| ื”ืชื—ื™ืœ| ืžืฉืš| ืžื“ื™ื ื”| ืฉืื™ืœืชื” +----------+-----------+-----------+-----+ --------- --+--------------------+------------------- --+------ --------------------------+---------------- ------- ------------------ | 1| 26211| tuser| psql| tdb1| 2019-09-02 19:31:54| 00:00:04| ื‘ื˜ืœื”| | 2| 26211| tuser| psql| tdb1| 2019-09-02 19:31:58| 00:00:06| ื‘ื˜ืœื” ื‘ืขืกืงื”| ื”ืชื—ืœ; | 3| 26211| tuser| psql| tdb1| 2019-09-02 19:32:16| 00:01:45| ื‘ื˜ืœื” ื‘ืขืกืงื”| ื ืขื™ืœืช ื˜ื‘ืœืช wafer_data; | 4| 26211| tuser| psql| tdb1| 2019-09-02 19:35:54| 00:01:23| ื‘ื˜ืœื”| ืœึฐื‘ึทืฆึตืขึท; | 5| 26211| tuser| psql| tdb1| 2019-09-02 19:38:46| 00:00:02| ื‘ื˜ืœื” ื‘ืขืกืงื”| ื”ืชื—ืœ; | 6| 26211| tuser| psql| tdb1| 2019-09-02 19:38:54| 00:00:08| ื‘ื˜ืœื” ื‘ืขืกืงื”| ื ืขื™ืœืช ื˜ื‘ืœืช wafer_data; | 7| 26211| tuser| psql| tdb1| 2019-09-02 19:39:08| 00:42:42| ื‘ื˜ืœื”| ืœึฐื‘ึทืฆึตืขึท; | 8| 26211| tuser| psql| tdb1| 2019-09-03 07:12:07| 00:00:52| ืคืขื™ืœ| ื‘ื—ืจ test_del();

ื”ืชืคืชื—ื•ืช.

ื”ืฉืื™ืœืชื•ืช ื”ื‘ืกื™ืกื™ื•ืช ื”ืžื•ืฆื’ื•ืช ื•ื”ื“ื•ื—ื•ืช ื”ืžืชืงื‘ืœื™ื ื›ื‘ืจ ื”ื•ืคื›ื™ื ืืช ื”ื—ื™ื™ื ืœื”ืจื‘ื” ื™ื•ืชืจ ืงืœื™ื ื‘ืขืช ื ื™ืชื•ื— ืชืงืจื™ื•ืช ื‘ื™ืฆื•ืขื™ื.
ื‘ื”ืชื‘ืกืก ืขืœ ืฉืื™ืœืชื•ืช ื‘ืกื™ืกื™ื•ืช, ืืชื” ื™ื›ื•ืœ ืœืงื‘ืœ ื“ื•ื— ืฉื“ื•ืžื” ื‘ืžืขื•ืจืคืœ ืœ-AWR ืฉืœ ืื•ืจืงืœ.
ื“ื•ื’ืžื” ืœื“ื•ื— ืกื™ื›ื•ื

+-------------------------------------------------------- ----------------------------------- | ื“ื•ื— ืžืื•ื—ื“ ืœืคืขื™ืœื•ืช ื•ื”ืžืชื ื”. 

ื”ืžืฉืš ื™ื‘ื•ื. ื”ื‘ื ื‘ืชื•ืจ ื”ื•ื ื™ืฆื™ืจืช ื”ื™ืกื˜ื•ืจื™ื™ืช ืžื ืขื•ืœื™ื (pg_stat_locks), ืชื™ืื•ืจ ืžืคื•ืจื˜ ื™ื•ืชืจ ืฉืœ ืชื”ืœื™ืš ืžื™ืœื•ื™ ื”ื˜ื‘ืœืื•ืช.

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”