Nỗ lực tạo một dạng tương tự của ASH cho PostgreSQL

Báo cáo sự cố

Để tối ưu hóa các truy vấn PostgreSQL, khả năng phân tích lịch sử hoạt động, đặc biệt là chờ đợi, khóa và thống kê bảng là rất cần thiết.

Cơ hội có sẵn

Công cụ phân tích khối lượng công việc lịch sử hoặc "AWR cho Postgres": một giải pháp rất thú vị, nhưng không có lịch sử của pg_stat_activity và pg_locks.

phần mở rộng pgsentinel :
«Tất cả thông tin tích lũy chỉ được lưu trữ trong RAM và dung lượng bộ nhớ tiêu thụ được điều chỉnh bởi số lượng bản ghi được lưu trữ cuối cùng.

Trường queryid được thêm vào - cùng một queryid từ phần mở rộng pg_stat_statements (yêu cầu cài đặt sẵn).«

Tất nhiên điều này sẽ giúp ích rất nhiều, nhưng điều rắc rối nhất là điểm đầu tiên.”Tất cả thông tin tích lũy chỉ được lưu trữ trong RAM ", I E. có tác động lên cơ sở mục tiêu. Ngoài ra, không có lịch sử khóa và thống kê bảng. Những thứ kia. giải pháp nói chung là không đầy đủ: “Chưa có gói làm sẵn để cài đặt. Bạn nên tải xuống các nguồn và tự lắp ráp thư viện. Trước tiên, bạn cần cài đặt gói “devel” cho máy chủ của mình và đặt đường dẫn đến pg_config trong biến PATH.".

Nói chung, có rất nhiều rắc rối và trong trường hợp cơ sở dữ liệu sản xuất nghiêm túc, có thể không thể làm được gì với máy chủ. Chúng ta cần phải nghĩ ra thứ gì đó của riêng mình một lần nữa.

Cảnh báo

Do khối lượng khá lớn và do thời gian thử nghiệm chưa đầy đủ nên bài viết chủ yếu mang tính chất thông tin hơn là tập hợp các luận văn và kết quả trung gian.
Tài liệu chi tiết hơn sẽ được chuẩn bị sau, theo từng phần

Dự thảo yêu cầu đối với giải pháp

Cần phát triển một công cụ cho phép bạn lưu trữ:

lịch sử xem pg_stat_activity
Lịch sử khóa phiên bằng chế độ xem pg_locks

Yêu cầu giải pháp–giảm thiểu tác động lên cơ sở dữ liệu mục tiêu.

Ý tưởng chung– tác nhân thu thập dữ liệu được khởi chạy không phải trong cơ sở dữ liệu đích mà trong cơ sở dữ liệu giám sát dưới dạng dịch vụ systemd. Có, có thể xảy ra mất một số dữ liệu, nhưng điều này không quan trọng đối với báo cáo nhưng không ảnh hưởng đến cơ sở dữ liệu đích về mặt bộ nhớ và dung lượng ổ đĩa. Và trong trường hợp sử dụng nhóm kết nối, tác động đến quy trình của người dùng là rất ít.

Các giai đoạn thực hiện

1. Bảng dịch vụ

Một lược đồ riêng được sử dụng để lưu trữ các bảng, để không làm phức tạp việc phân tích các bảng chính được sử dụng.

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

Quan trọng: Lược đồ không được tạo trong cơ sở dữ liệu đích mà trong cơ sở dữ liệu giám sát.

lịch sử xem pg_stat_activity

Một bảng được sử dụng để lưu trữ ảnh chụp nhanh hiện tại của chế độ xem pg_stat_activity

hoạt động_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
);

Để tăng tốc độ chèn - không có chỉ mục hoặc hạn chế.

Để lưu trữ lịch sử, một bảng được phân vùng được sử dụng:

hoạt động_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);

Vì trong trường hợp này không có yêu cầu về tốc độ chèn nên một số chỉ mục đã được tạo để tăng tốc độ tạo báo cáo.

Lịch sử chặn phiên

Một bảng được sử dụng để lưu trữ ảnh chụp nhanh hiện tại của khóa phiên:

hoạt động_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
);

Ngoài ra, để tăng tốc độ chèn, không có chỉ mục hoặc hạn chế nào.

Để lưu trữ lịch sử, một bảng được phân vùng được sử dụng:

hoạt động_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);

Vì trong trường hợp này không có yêu cầu về tốc độ chèn nên một số chỉ mục đã được tạo để tăng tốc độ tạo báo cáo.

2. Điền vào lịch sử hiện tại

Để thu thập trực tiếp các ảnh chụp nhanh của chế độ xem, một tập lệnh bash chạy hàm plpgsql được sử dụng.

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 Hàm dblink truy cập các dạng xem trong cơ sở dữ liệu đích và chèn các hàng vào các bảng dịch vụ trong cơ sở dữ liệu giám sát.

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;

Để thu thập ảnh chụp nhanh của chế độ xem, dịch vụ systemd và hai tập lệnh được sử dụng:

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

Gán quyền cho script:
# chmod 755 pg_current_activity.timer
# chmod 755 pg_current_activity.service

Hãy bắt đầu dịch vụ:
# systemctl daemon-tải lại
# systemctl bắt đầu pg_current_activity.service

Do đó, lịch sử lượt xem được thu thập dưới dạng ảnh chụp nhanh từng giây. Tất nhiên, nếu mọi thứ vẫn như cũ, các bảng sẽ tăng kích thước rất nhanh và ít nhiều công việc hiệu quả sẽ trở nên bất khả thi.

Cần tổ chức lưu trữ dữ liệu.

3. Lịch sử lưu trữ

Để lưu trữ, kho lưu trữ bảng phân vùng* được sử dụng.

Các phân vùng mới được tạo mỗi giờ, trong khi dữ liệu cũ bị xóa khỏi bảng history*, do đó kích thước của bảng history* không thay đổi nhiều và tốc độ chèn không giảm theo thời gian.

Việc tạo các phần mới được thực hiện bởi hàm plpgsql hoạt động_hist.archive_current_activity. Thuật toán làm việc rất đơn giản (sử dụng ví dụ về phần dành cho bảng archive_pg_stat_activity).

Tạo và điền vào một phần mới

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 		
);

Tạo chỉ mục

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 )' 
);

Xóa dữ liệu cũ khỏi bảng history_pg_stat_activity

DELETE 
FROM 	activity_hist.history_pg_stat_activity
WHERE 	timepoint < partition_max_range;

Tất nhiên, đôi khi những phần cũ sẽ bị xóa vì không cần thiết.

Báo cáo cơ bản

Trên thực tế, tại sao tất cả những điều này lại được thực hiện? Để có được những báo cáo gợi nhớ rất mơ hồ về AWR của Oracle.

Điều quan trọng cần nói thêm là để nhận được báo cáo, bạn cần tạo kết nối giữa chế độ xem pg_stat_activity và pg_stat_statements. Các bảng được liên kết bằng cách thêm cột 'queryid' vào các bảng 'history_pg_stat_activity', 'archive_pg_stat_activity'. Phương pháp thêm giá trị cột nằm ngoài phạm vi của bài viết này và được mô tả ở đây - pg_stat_statements + pg_stat_activity + loq_query = pg_ash? .

TỔNG THỜI GIAN CPU CHO TRUY VẤN

Lời yêu cầu :

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

Ví dụ:

-------------------------------------------------------------------
| 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
+----+----------------------------------------+--------------------

TỔNG THỜI GIAN CHỜ ĐỢI CHO TRUY VẤN

Lời yêu cầu :

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 

Ví dụ:

-------------------------------------------------------------------
| 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
+----+----------------------------------------+--------------------

CHỜ TRUY VẤN

Yêu cầu:

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

Ví dụ:

------------------------------------------------
| 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

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

LỊCH SỬ QUY TRÌNH BỊ KHÓA

Lời yêu cầu:

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

Ví dụ:

-------------------------------------------------- -------------------------------------------------- --------------------------------- | LỊCH SỬ QUY TRÌNH BỊ KHÓA +------+----------+------+-------- --+------------- ---------+-----------+------ --------------- +------------------- | #| pid| bắt đầu| thời lượng| chặn_pids| quan hệ| chế độ| loại khóa +----------+----------+------+---------- +-------- -------------+----------+------- -------------+------ -------------- | 1| 26224| 2019-09-02 19:32:16| 00:01:45| {26211}| 16541| Truy cậpShareLock| quan hệ | 2| 26390| 2019-09-02 19:34:03| 00:00:53| {26211}| 16541| Truy cậpShareLock| quan hệ | 3| 26391| 2019-09-02 19:34:03| 00:00:53| {26211}| 16541| Truy cậpShareLock| quan hệ | 4| 26531| 2019-09-02 19:35:27| 00:00:12| {26211}| 16541| Truy cậpShareLock| quan hệ | 5| 27284| 2019-09-02 19:44:02| 00:00:19| {27276}| 16541| Truy cậpShareLock| quan hệ | 6| 27283| 2019-09-02 19:44:02| 00:00:19| {27276}| 16541| Truy cậpShareLock| quan hệ | 7| 27286| 2019-09-02 19:44:02| 00:00:19| {27276}| 16541| Truy cậpShareLock| quan hệ | 8| 27423| 2019-09-02 19:45:24| 00:00:12| {27394}| 16541| Truy cậpShareLock| quan hệ | 9| 27648| 2019-09-02 19:48:06| 00:00:20| {27647}| 16541| Truy cậpShareLock| quan hệ | 10| 27650| 2019-09-02 19:48:06| 00:00:20| {27647}| 16541| Truy cậpShareLock| quan hệ | 11| 27735| 2019-09-02 19:49:08| 00:00:06| {27650}| 16541| Truy cậpKhóa độc quyền| quan hệ | 12| 28380| 2019-09-02 19:56:03| 00:01:56| {28379}| 16541| Truy cậpShareLock| quan hệ | 13| 28379| 2019-09-02 19:56:03| 00:00:01| 28377| 16541| Truy cậpKhóa độc quyền| quan hệ | | | | | 28376| | 

LỊCH SỬ QUY TRÌNH CHẶN

Yêu cầu:

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

Ví dụ:

-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------- LỊCH SỬ QUY TRÌNH CHẶN +----+----------+------- ---+-------------------+----------+-------------- ------+-------------------++---------------------- - -------+--------------------------------------- | #| pid| tên người dùng| ứng dụng_name| datname| bắt đầu| thời lượng| tiểu bang| truy vấn +----------+----------+----------+------+ --------- -+----------------------+------------------- --+------ --------------------------+------- ------- ----------------- | 1| 26211| người dùng| psql| tdb1| 2019-09-02 19:31:54| 00:00:04| nhàn rỗi| | 2| 26211| người dùng| psql| tdb1| 2019-09-02 19:31:58| 00:00:06| nhàn rỗi trong giao dịch| bắt đầu; | 3| 26211| người dùng| psql| tdb1| 2019-09-02 19:32:16| 00:01:45| nhàn rỗi trong giao dịch| khóa bảng wafer_data; | 4| 26211| người dùng| psql| tdb1| 2019-09-02 19:35:54| 00:01:23| nhàn rỗi| làm; | 5| 26211| người dùng| psql| tdb1| 2019-09-02 19:38:46| 00:00:02| nhàn rỗi trong giao dịch| bắt đầu; | 6| 26211| người dùng| psql| tdb1| 2019-09-02 19:38:54| 00:00:08| nhàn rỗi trong giao dịch| khóa bảng wafer_data; | 7| 26211| người dùng| psql| tdb1| 2019-09-02 19:39:08| 00:42:42| nhàn rỗi| làm; | 8| 26211| người dùng| psql| tdb1| 2019-09-03 07:12:07| 00:00:52| hoạt động| chọn test_del();

Sự phát triển.

Các truy vấn cơ bản được hiển thị và các báo cáo kết quả đã giúp công việc phân tích các sự cố về hiệu suất trở nên dễ dàng hơn nhiều.
Dựa trên các truy vấn cơ bản, bạn có thể nhận được một báo cáo gần giống với AWR của Oracle.
Ví dụ về báo cáo tóm tắt

+------------------------------------------------ ----------------------------------- | BÁO CÁO TỔNG HỢP VỀ HOẠT ĐỘNG VÀ CHỜ ĐỢI. 

Còn tiếp. Tiếp theo là tạo lịch sử khóa (pg_stat_locks), mô tả chi tiết hơn về quá trình điền vào bảng.

Nguồn: www.habr.com

Thêm một lời nhận xét