Следење на перформансите на барањето PostgreSQL. Дел 1 - известување

Инженер - преведено од латински - инспириран.
Инженерот може да направи се. (в) R. Дизел.
Епиграфи.
Следење на перформансите на барањето PostgreSQL. Дел 1 - известување
Или приказна за тоа зошто администраторот на базата на податоци треба да се сеќава на своето програмско минато.

предговорот

Сите имиња се сменети. Случајностите се случајни. Материјалот го претставува исклучиво личното мислење на авторот.

Одрекување од гаранции: Планираната серија на написи нема да содржи детален и точен опис на користените табели и скрипти. Материјалите не можат веднаш да се користат „КАКО СЕ“.
Прво, поради големиот обем на материјал,
второ, поради блиската врска со производствената база на вистински клиент.
Затоа, написите ќе содржат само идеи и описи во најопштата форма.
Можеби во иднина системот ќе порасне до степен да биде објавен на GitHub, или можеби не. Времето ќе покаже.

Почетокот на приказната - "Се сеќавате ли како започна се".
Што се случи како резултат, во најопшта смисла - “Синтезата како еден од методите за подобрување на перформансите на PostgreSQL»

Зошто ми треба сето ова?

Па, прво, за да не заборавиме, сеќавајќи се на славните денови во пензија.
Второ, да се систематизира напишаното. Затоа што понекогаш почнувам да се збунувам и да заборавам одредени делови.

Па, и најважно е дека некому може да му се најде и да избегне повторно да го измисли тркалото и да не собира гребло. Со други зборови, подобрете ја вашата карма (не онаа на Хабров). Затоа што највредното нешто на овој свет се идеите. Главната работа е да се најде идеја. Но, претворањето на идејата во реалност е чисто техничко прашање.

Значи, да почнеме, малку по малку...

Формулирање на проблемот.

Достапно:

PostgreSQL(10.5) база на податоци, мешан тип на оптоварување (OLTP+DSS), средно светло оптоварување, лоцирано во облакот AWS.
Не постои мониторинг на базата на податоци.

Потребно:

Следете ги перформансите и статусот на базата на податоци, најдете и имајте првични информации за оптимизирање на тешките барања за базата на податоци.

Краток вовед или анализа на опциите за решение

За почеток, да се обидеме да ги анализираме опциите за решавање на проблемот од гледна точка на компаративна анализа на придобивките и недостатоците за инженерот, а оние што имаат право на тоа според распоредот на персоналот нека се занимаваат со придобивките и загуби на управување.

Опција 1 - „Работа на барање“

Оставаме сè како што е. Доколку клиентот не е задоволен со нешто во функционалноста, перформансите на базата или апликацијата, тој ќе ги извести инженерите на DBA преку е-пошта или со создавање инцидент во фиоката за билети.
Инженерот, откако го добил известувањето, ќе го разбере проблемот, ќе понуди решение или ќе го стави проблемот на задниот режач, надевајќи се дека сè ќе се реши само по себе, и како и да е, сè наскоро ќе биде заборавено.
Джинджифилово и крофни, модринки и испакнатиниДжинджифилово и крофни:
1. Нема потреба да правите ништо дополнително.
2. Секогаш постои можност да барате изговори и да се зафркавате.
3. Многу време што можете да го потрошите по сопствена дискреција.
Модринки и испакнатини:
1. Порано или подоцна, клиентот ќе размисли за суштината на постоењето и универзалната правда на овој свет и уште еднаш ќе си го постави прашањето - зошто им ги плаќам моите пари? Последицата е секогаш иста - единственото прашање е кога на клиентот ќе му здосади и ќе мавне збогум. И фидерот ќе биде празен. Тажно е.
2. Развој на инженери - нула.
3. Тешкотии во планирањето на работата и товарењето

Опција 2- „Танцување со тамбураши, парење и облекување чевли“

Став 1-Зошто ни треба мониторинг систем, се ќе добиваме со барања. Испраќаме куп секакви прашања до речникот на податоци и динамички прикази, вклучуваме секакви бројачи, ставаме сè во табели и периодично анализираме списоци и табели. Како резултат на тоа, имаме убави или не толку убави графикони, табели, извештаи. Главната работа е да има повеќе, повеќе.
Став 2-Генерираме активност и ја започнуваме анализата на сето ова.
Став 3-Подготвуваме одреден документ, овој документ го нарекуваме едноставно - „како да поставиме база на податоци“.
Став 4-Корисникот, гледајќи го целиот овој раскош на графикони и бројки, е во детска, наивна доверба - сега сè ќе ни функционира, наскоро. А, лесно и безболно се разделува со своите финансиски средства. Раководството е исто така уверено дека нашите инженери работат одлично. Се вчитува максимално.
Став 5-Редовно повторувајте го чекорот 1.
Джинджифилово и крофни, модринки и испакнатиниДжинджифилово и крофни:
1. Животот на менаџерите и инженерите е едноставен, предвидлив и исполнет со активност. Сè зуе, сите се зафатени.
2. Животот на купувачот исто така не е лош - тој е секогаш сигурен дека само треба да биде малку трпелив и сè ќе успее. Не се подобрува, добро, светот е неправеден, во следниот живот ќе имате среќа.
Модринки и испакнатини:
1. Порано или подоцна, ќе има побрз давател на слична услуга кој ќе го прави истото, но малку поевтино. И ако резултатот е ист, зошто да платите повеќе. Што повторно ќе доведе до исчезнување на фидер.
2. Досадно е. Колку е досадна секоја бесмислена активност.
3. Како и во претходната верзија, нема развој. Но, за еден инженер, негативната страна е тоа што, за разлика од првата опција, треба постојано да генерирате IBD. И за ова е потребно време. Кои можете да ги потрошите во корист на вашата сакана. Бидејќи не можете да се грижите за себе, никој не се грижи за вас.

Опција 3 - Не треба да измислувате велосипед, само треба да го купите и да го возите.

Не е за џабе инженерите од други компании јадат пица со пиво (ох, славните денови на Санкт Петербург во 90-тите). Ајде да користиме системи за следење што се направени, дебагирани и работат, и општо земено корист (добро, барем за нивните креатори).
Джинджифилово и крофни, модринки и испакнатиниДжинджифилово и крофни:
1. Нема потреба да губите време за да смислите нешто што е веќе измислено. Земете го и искористете го.
2. Системите за мониторинг не се напишани од будали и тие се, се разбира, корисни.
3. Работните системи за следење обично обезбедуваат корисни филтрирани информации.
Модринки и испакнатини:
1. Инженерот во овој случај не е инженер, туку само корисник на туѓ производ или корисник.
2. Клиентот мора да биде убеден во потребата да купи нешто што, генерално кажано, не сака да го разбере, и не треба, и воопшто буџетот за годината е одобрен и нема да се промени. Потоа треба да одвоите посебен ресурс и да го конфигурирате за одреден систем. Оние. прво треба да платите, да платите и повторно да платите. А муштеријата е скржав. Ова е норма на овој живот.

Што да правам - Чернишевски? Вашето прашање е многу релевантно. (Со)

Во овој конкретен случај и моменталната ситуација, можете да го направите тоа малку поинаку - ајде да направиме свој систем за следење.
Следење на перформансите на барањето PostgreSQL. Дел 1 - известување
Па, не е систем, се разбира, во целосна смисла на зборот, кој е премногу гласен и дрзок, но барем некако ќе ви ја олесни задачата и ќе собере повеќе информации за да ги реши инцидентите со перформансите. За да не се најдете во ситуација - „одете таму, не знам каде, најдете нешто, не знам што“.

Кои се добрите и лошите страни на оваа опција:

Позитивни:
1. Ова е интересно. Па, барем тоа е поинтересно од константното „смалување на датотеката со податоци, менување на просторот на маса, итн.“
2. Тоа се нови вештини и нов развој. Кои, порано или подоцна, ќе ви ги дадат заслужените джинджифилово и крофни.
Конс:
1. Ќе мора да работите. Работете напорно.
2. Ќе мора редовно да го објаснувате значењето и перспективите на сите активности.
3. Нешто ќе треба да се жртвува, бидејќи единствениот ресурс на располагање на инженерот - времето - е ограничен од Универзумот.
4. Најлошото и најнепријатното нешто - резултатот може да биде срање како „Не глушец, не жаба, туку непознато животно“.

Оние кои не ризикуваат не пијат шампањ.
Така - забавата започнува.

Општа идеја - шематски

Следење на перформансите на барањето PostgreSQL. Дел 1 - известување
(Илустрација земена од статијата «Синтезата како еден од методите за подобрување на перформансите на PostgreSQL")

Објаснување:

  • Стандардната екстензија PostgreSQL „pg_stat_statements“ е инсталирана во целната база на податоци.
  • Во базата на податоци за следење, создаваме збир на табели за услуги за складирање на историјата на pg_stat_statements во почетната фаза и за поставување метрика и следење во иднина
  • На домаќинот за следење, создаваме збир на баш скрипти, вклучувајќи ги и оние за генерирање инциденти во системот за билети.

Сервисни маси

Прво, шематски поедноставен ERD, што се случи на крајот:
Следење на перформансите на барањето PostgreSQL. Дел 1 - известување
Краток опис на табелитекрајната точка — домаќин, точка на поврзување со инстанцата
база на податоци - параметри на базата на податоци
pg_stat_istory - историска табела за складирање привремени снимки од приказот pg_stat_statements на целната база на податоци
метрички_речник - речник на метрика на перформанси
метричка_конфигурација — конфигурација на поединечни метрика
метрички — специфична метрика за барањето што се следи
метричка_историја на предупредување - историја на предупредувања за изведба
log_query — табела за услуги за складирање анализирани записи од датотека за евиденција PostgreSQL преземена од AWS
основно — параметри на временските периоди што се користат како основа
контролен пункт — конфигурација на метрика за проверка на статусот на базата на податоци
checkpoint_alert_istory — предупредувачка историја на метрика за здравствена проверка на базата на податоци
pg_stat_db_queries — сервисна табела на активни барања
активност_дневник — Табела за услуга на дневникот на активности
trap_oid — Табела за услуга за конфигурација на стапица

Фаза 1 - собирајте статистички информации за перформансите и примајте извештаи

Табела се користи за складирање на статистички информации pg_stat_istory
Структура на табелата pg_stat_history

                                          Табела „public.pg_stat_history“ Колона | Тип | Модификатори------------------------------------------------ -+------------------------------------------ ид | цел број | не е нула стандардно nextval('pg_stat_history_id_seq'::regclass) snapshot_timestamp | временски печат без временска зона | ID_база на податоци | цел број | dbid | оид | userid | оид | прашалник | бигинт | барање | текст | повици | бигинт | вкупно_време | двојна прецизност | мин_време | двојна прецизност | max_time | двојна прецизност | средно_време | двојна прецизност | stddev_time | двојна прецизност | редови | бигинт | shared_blks_hit | бигинт | shared_blks_read | бигинт | shared_blks_dirtied | бигинт | споделени_блкс_напишани | бигинт | local_blks_hit | бигинт | локално_блкс_читање | бигинт | локални_блкс_извалкани | бигинт | локално_блкс_напишано | бигинт | temp_blks_читање | бигинт | temp_blks_напишано | бигинт | blk_time_read | двојна прецизност | blk_write_time | двојна прецизност | основна_идентификација | цел број | Индекси: "pg_stat_history_pkey" ПРИМАРЕН КЛУЧ, btree (id) "database_idx" btree (database_id) "queryid_idx" btree (queryid) "snapshot_timestamp_idx" btree (snapshot_timestamp) "Foreign_timestamp" (NIGdaase_tabase) РЕФЕРЕНЦИ база на податоци (ид ) НА БРИШЕЊЕ КАСКАДА

Како што можете да видите, табелата е само кумулативен приказ на податоци pg_stat_statements во целната база на податоци.

Користењето на оваа табела е многу едноставно

pg_stat_istory ќе претставува акумулирана статистика за извршување на барањето за секој час. На почетокот на секој час, по пополнување на табелата, статистика pg_stat_statements ресетирање со pg_stat_statements_reset().
Забелешка: Статистиката се собира за прашања со времетраење на извршување од повеќе од 1 секунда.
Пополнување на табелата pg_stat_history

--pg_stat_history.sql
CREATE OR REPLACE FUNCTION pg_stat_history( ) RETURNS boolean AS $$
DECLARE
  endpoint_rec record ;
  database_rec record ;
  pg_stat_snapshot record ;
  current_snapshot_timestamp timestamp without time zone;
BEGIN
  current_snapshot_timestamp = date_trunc('minute',now());  
  
  FOR endpoint_rec IN SELECT * FROM endpoint 
  LOOP
    FOR database_rec IN SELECT * FROM database WHERE endpoint_id = endpoint_rec.id 
	  LOOP
	    
		RAISE NOTICE 'NEW SHAPSHOT IS CREATING';
		
		--Connect to the target DB	  
	    EXECUTE 'SELECT dblink_connect(''LINK1'',''host='||endpoint_rec.host||' dbname='||database_rec.name||' user=USER password=PASSWORD '')';
 
        RAISE NOTICE 'host % and dbname % ',endpoint_rec.host,database_rec.name;
		RAISE NOTICE 'Creating snapshot of pg_stat_statements for database %',database_rec.name;
		
		SELECT 
	      *
		INTO 
		  pg_stat_snapshot
	    FROM dblink('LINK1',
	      'SELECT 
	       dbid , SUM(calls),SUM(total_time),SUM(rows) ,SUM(shared_blks_hit) ,SUM(shared_blks_read) ,SUM(shared_blks_dirtied) ,SUM(shared_blks_written) , 
           SUM(local_blks_hit) , SUM(local_blks_read) , SUM(local_blks_dirtied) , SUM(local_blks_written) , SUM(temp_blks_read) , SUM(temp_blks_written) , SUM(blk_read_time) , SUM(blk_write_time)
	       FROM pg_stat_statements WHERE dbid=(SELECT oid from pg_database where datname=current_database() ) 
		   GROUP BY dbid
  	      '
	               )
	      AS t
	       ( dbid oid , calls bigint , 
  	         total_time double precision , 
	         rows bigint , shared_blks_hit bigint , shared_blks_read bigint ,shared_blks_dirtied bigint ,shared_blks_written	 bigint ,
             local_blks_hit	 bigint ,local_blks_read bigint , local_blks_dirtied bigint ,local_blks_written bigint ,
             temp_blks_read	 bigint ,temp_blks_written bigint ,
             blk_read_time double precision , blk_write_time double precision	  
	       );
		 
		INSERT INTO pg_stat_history
          ( 
		    snapshot_timestamp  ,database_id  ,
			dbid , calls  ,total_time ,
            rows ,shared_blks_hit  ,shared_blks_read  ,shared_blks_dirtied  ,shared_blks_written ,local_blks_hit , 	 	
            local_blks_read,local_blks_dirtied,local_blks_written,temp_blks_read,temp_blks_written, 	
            blk_read_time, blk_write_time 
		  )		  
	    VALUES
	      (
	       current_snapshot_timestamp ,
		   database_rec.id ,
	       pg_stat_snapshot.dbid ,pg_stat_snapshot.calls,
	       pg_stat_snapshot.total_time,
	       pg_stat_snapshot.rows ,pg_stat_snapshot.shared_blks_hit ,pg_stat_snapshot.shared_blks_read ,pg_stat_snapshot.shared_blks_dirtied ,pg_stat_snapshot.shared_blks_written , 
           pg_stat_snapshot.local_blks_hit , pg_stat_snapshot.local_blks_read , pg_stat_snapshot.local_blks_dirtied , pg_stat_snapshot.local_blks_written , 
	       pg_stat_snapshot.temp_blks_read , pg_stat_snapshot.temp_blks_written , pg_stat_snapshot.blk_read_time , pg_stat_snapshot.blk_write_time 	   
	      );		   
		  
        RAISE NOTICE 'Creating snapshot of pg_stat_statements for queries with min_time more than 1000ms';
	
        FOR pg_stat_snapshot IN
          --All queries with max_time greater than 1000 ms
	      SELECT 
	        *
	      FROM dblink('LINK1',
	        'SELECT 
	         dbid , userid ,queryid,query,calls,total_time,min_time ,max_time,mean_time, stddev_time ,rows ,shared_blks_hit ,
			 shared_blks_read ,shared_blks_dirtied ,shared_blks_written , 
             local_blks_hit , local_blks_read , local_blks_dirtied , 
			 local_blks_written , temp_blks_read , temp_blks_written , blk_read_time , 
			 blk_write_time
	         FROM pg_stat_statements 
			 WHERE dbid=(SELECT oid from pg_database where datname=current_database() AND min_time >= 1000 ) 
  	        '

	                  )
	        AS t
	         ( dbid oid , userid oid , queryid bigint ,query text , calls bigint , 
  	           total_time double precision ,min_time double precision	 ,max_time double precision	 , mean_time double precision	 ,  stddev_time double precision	 , 
	           rows bigint , shared_blks_hit bigint , shared_blks_read bigint ,shared_blks_dirtied bigint ,shared_blks_written	 bigint ,
               local_blks_hit	 bigint ,local_blks_read bigint , local_blks_dirtied bigint ,local_blks_written bigint ,
               temp_blks_read	 bigint ,temp_blks_written bigint ,
               blk_read_time double precision , blk_write_time double precision	  
	         )
	    LOOP
		  INSERT INTO pg_stat_history
          ( 
		    snapshot_timestamp  ,database_id  ,
			dbid ,userid  , queryid  , query  , calls  ,total_time ,min_time ,max_time ,mean_time ,stddev_time ,
            rows ,shared_blks_hit  ,shared_blks_read  ,shared_blks_dirtied  ,shared_blks_written ,local_blks_hit , 	 	
            local_blks_read,local_blks_dirtied,local_blks_written,temp_blks_read,temp_blks_written, 	
            blk_read_time, blk_write_time 
		  )		  
	      VALUES
	      (
	       current_snapshot_timestamp ,
		   database_rec.id ,
	       pg_stat_snapshot.dbid ,pg_stat_snapshot.userid ,pg_stat_snapshot.queryid,pg_stat_snapshot.query,pg_stat_snapshot.calls,
	       pg_stat_snapshot.total_time,pg_stat_snapshot.min_time ,pg_stat_snapshot.max_time,pg_stat_snapshot.mean_time, pg_stat_snapshot.stddev_time ,
	       pg_stat_snapshot.rows ,pg_stat_snapshot.shared_blks_hit ,pg_stat_snapshot.shared_blks_read ,pg_stat_snapshot.shared_blks_dirtied ,pg_stat_snapshot.shared_blks_written , 
           pg_stat_snapshot.local_blks_hit , pg_stat_snapshot.local_blks_read , pg_stat_snapshot.local_blks_dirtied , pg_stat_snapshot.local_blks_written , 
	       pg_stat_snapshot.temp_blks_read , pg_stat_snapshot.temp_blks_written , pg_stat_snapshot.blk_read_time , pg_stat_snapshot.blk_write_time 	   
	      );
		  
        END LOOP;

        PERFORM dblink_disconnect('LINK1');  
				
	  END LOOP ;--FOR database_rec IN SELECT * FROM database WHERE endpoint_id = endpoint_rec.id 
    
  END LOOP;

RETURN TRUE;  
END
$$ LANGUAGE plpgsql;

Како резултат на тоа, по одреден временски период во табелата pg_stat_istory ќе имаме збир на снимки од содржината на табелата pg_stat_statements целна база на податоци.

Всушност известување

Користејќи едноставни прашања, можете да добиете доста корисни и интересни извештаи.

Агрегирани податоци за даден временски период

Барање

SELECT 
  database_id , 
  SUM(calls) AS calls ,SUM(total_time)  AS total_time ,
  SUM(rows) AS rows , SUM(shared_blks_hit)  AS shared_blks_hit,
  SUM(shared_blks_read) AS shared_blks_read ,
  SUM(shared_blks_dirtied) AS shared_blks_dirtied,
  SUM(shared_blks_written) AS shared_blks_written , 
  SUM(local_blks_hit) AS local_blks_hit , 
  SUM(local_blks_read) AS local_blks_read , 
  SUM(local_blks_dirtied) AS local_blks_dirtied , 
  SUM(local_blks_written)  AS local_blks_written,
  SUM(temp_blks_read) AS temp_blks_read, 
  SUM(temp_blks_written) temp_blks_written , 
  SUM(blk_read_time) AS blk_read_time , 
  SUM(blk_write_time) AS blk_write_time
FROM 
  pg_stat_history
WHERE 
  queryid IS NULL AND
  database_id = DATABASE_ID  AND
  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT
GROUP BY database_id ;

Време на ДБ

до_char(интервал „1 милисекунда“ * pg_total_stat_history_rec.total_time, „HH24:MI:SS.MS“)

Време на I/O

to_char (интервал „1 милисекунда“ * ( pg_total_stat_history_rec.blk_read_time + pg_total_stat_history_rec.blk_write_time ), „HH24:MI:SS.MS“)

TOP10 SQL според total_time

Барање

SELECT 
  queryid , 
  SUM(calls) AS calls ,
  SUM(total_time)  AS total_time  	
FROM 
  pg_stat_history
WHERE 
  queryid IS NOT NULL AND 
  database_id = DATABASE_ID AND
  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT 
GROUP BY queryid 
ORDER BY 3 DESC 
LIMIT 10
------------------------------------------------- ------------------------------------ | ТОП10 SQL ПО ВКУПНО ВРЕМЕ НА ИЗВРШУВАЊЕ | #| прашалник| повици| повикува %| вкупно_време (ms) | dbtime % +----------+-----------------------+------------+ ------ -------------------------------------- | 1| 821760255| 2| .00001|00:03:23.141( 203141.681 ms.)| 5.42 | 2| 4152624390| 2| .00001|00:03:13.929( 193929.215 ms.)| 5.17 | 3| 1484454471| 4| .00001|00:02:09.129( 129129.057 ms.)| 3.44 | 4| 655729273| 1| .00000|00:02:01.869( 121869.981 ms.)| 3.25 | 5| 2460318461| 1| .00000|00:01:33.113( 93113.835 ms.)| 2.48 | 6| 2194493487| 4| .00001|00:00:17.377( 17377.868 ms.)| .46 | 7| 1053044345| 1| .00000|00:00:06.156( 6156.352 ms.)| .16 | 8| 3644780286| 1| .00000|00:00:01.063( 1063.830 ms.)| .03

TOP10 SQL според вкупното време на влез/излез

Барање

SELECT 
  queryid , 
  SUM(calls) AS calls ,
  SUM(blk_read_time + blk_write_time)  AS io_time
FROM 
  pg_stat_history
WHERE 
  queryid IS NOT NULL AND 
  database_id = DATABASE_ID  AND
  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT
GROUP BY  queryid 
ORDER BY 3 DESC 
LIMIT 10
------------------------------------------------- -------------------------------------- | ТОП10 SQL ПО ВКУПНО В/И ВРЕМЕ | #| прашалник| повици| повикува %| Време на влез/излез (ms)|db време на влез/излез % +----+-----------+------------------- -----------+--------------------------------------- ------ -- | 1| 4152624390| 2| .00001|00:08:31.616( 511616.592 ms.)| 31.06 | 2| 821760255| 2| .00001|00:08:27.099( 507099.036 ms.)| 30.78 | 3| 655729273| 1| .00000|00:05:02.209( 302209.137 ms.)| 18.35 часот | 4| 2460318461| 1| .00000|00:04:05.981( 245981.117 ms.)| 14.93 | 5| 1484454471| 4| .00001|00:00:39.144( 39144.221 ms.)| 2.38 | 6| 2194493487| 4| .00001|00:00:18.182( 18182.816 ms.)| 1.10 | 7| 1053044345| 1| .00000|00:00:16.611( 16611.722 ms.)| 1.01 | 8| 3644780286| 1| .00000|00:00:00.436( 436.205 ms.)| .03

TOP10 SQL по максимално време на извршување

Барање

SELECT 
  id AS snapshotid , 
  queryid , 
  snapshot_timestamp ,  
  max_time 
FROM 
  pg_stat_history 
WHERE 
  queryid IS NOT NULL AND 
  database_id = DATABASE_ID  AND
  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT
ORDER BY 4 DESC 
LIMIT 10

------------------------------------------------- --------------------------------------- | ТОП10 SQL ПО МАКСИЛНО ВРЕМЕ НА ИЗВРШУВАЊЕ | #| слика| ИД на слика| прашалник| max_time (ms) +----+----------------------------------------- --+--------------------------------------- | 1| 05.04.2019 01:03| 4169| 655729273| 00:02:01.869( 121869.981 ms.) | 2| 04.04.2019 17:00 часот| 4153| 821760255| 00:01:41.570 ( 101570.841 ms.) | 3| 04.04.2019 16:00 часот| 4146| 821760255| 00:01:41.570 ( 101570.841 ms.) | 4| 04.04.2019 16:00 часот| 4144| 4152624390| 00:01:36.964(96964.607 ms.) | 5| 04.04.2019 17:00 часот| 4151| 4152624390| 00:01:36.964(96964.607 ms.) | 6| 05.04.2019 10:00| 4188| 1484454471| 00:01:33.452 ( 93452.150 ms.) | 7| 04.04.2019 17:00 часот| 4150| 2460318461| 00:01:33.113( 93113.835 ms.) | 8| 04.04.2019 15:00 часот| 4140| 1484454471| 00:00:11.892 ( 11892.302 ms.) | 9| 04.04.2019 16:00 часот| 4145| 1484454471| 00:00:11.892 ( 11892.302 ms.) | 10| 04.04.2019 17:00 часот| 4152| 1484454471| 00:00:11.892 (11892.302 ms.)

TOP10 SQL од SHARED бафер за читање/запишување

Барање

SELECT 
  id AS snapshotid , 
  queryid ,
  snapshot_timestamp , 
  shared_blks_read , 
  shared_blks_written 
FROM 
  pg_stat_history
WHERE 
  queryid IS NOT NULL AND 
  database_id = DATABASE_ID  AND
  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT AND
  ( shared_blks_read > 0 OR shared_blks_written > 0 )
ORDER BY 4 DESC  , 5 DESC 
LIMIT 10
------------------------------------------------- ------------------------------------------ | ТОП10 SQL СО СПОДЕЛЕН БАФЕР ЧИТАЊЕ/ПИШУВАЊЕ | #| слика| ИД на слика| прашалник| споделени блокови читаат| споделените блокови пишуваат +----+----------------------------------------- -+---------------------+--------------------- | 1| 04.04.2019 17:00 часот| 4153| 821760255| 797308| 0 | 2| 04.04.2019 16:00 часот| 4146| 821760255| 797308| 0 | 3| 05.04.2019 01:03| 4169| 655729273| 797158| 0 | 4| 04.04.2019 16:00 часот| 4144| 4152624390| 756514| 0 | 5| 04.04.2019 17:00 часот| 4151| 4152624390| 756514| 0 | 6| 04.04.2019 17:00 часот| 4150| 2460318461| 734117| 0 | 7| 04.04.2019 17:00 часот| 4155| 3644780286| 52973| 0 | 8| 05.04.2019 01:03| 4168| 1053044345| 52818| 0 | 9| 04.04.2019 15:00 часот| 4141| 2194493487| 52813| 0 | 10| 04.04.2019 16:00 часот| 4147| 2194493487| 52813| 0 ------------------------------------------------- --------------------------------------------

Хистограм на дистрибуција на барања по максимално време на извршување

Барања

SELECT  
  MIN(max_time) AS hist_min  , 
  MAX(max_time) AS hist_max , 
  (( MAX(max_time) - MIN(min_time) ) / hist_columns ) as hist_width
FROM 
  pg_stat_history 
WHERE 
  queryid IS NOT NULL AND
  database_id = DATABASE_ID  AND
  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT ;

SELECT 
  SUM(calls) AS calls
FROM 
  pg_stat_history 
WHERE 
  queryid IS NOT NULL AND
  database_id =DATABASE_ID  AND
  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT AND 
  ( max_time >= hist_current_min AND  max_time < hist_current_max ) ;
|------------------------------------------------ --------------------------------------------- | MAX_TIME ХИСТОГРАМ | ВКУПНО ПОВИКИ: 33851920 | MIN ВРЕМЕ: 00:00:01.063 | МАКС ВРЕМЕ: 00:02:01.869 ------------------------------------------ --------------------------------------- | мин времетраење| максимално времетраење| повици +---------------------------------+------------- ---------------------+---------- | 00:00:01.063( 1063.830 ms.) | 00:00:13.144 ( 13144.445 ms.) | 9 | 00:00:13.144 ( 13144.445 ms.) | 00:00:25.225( 25225.060 ms.) | 0 | 00:00:25.225( 25225.060 ms.) | 00:00:37.305 ( 37305.675 ms.) | 0 | 00:00:37.305 ( 37305.675 ms.) | 00:00:49.386 ( 49386.290 ms.) | 0 | 00:00:49.386 ( 49386.290 ms.) | 00:01:01.466 ( 61466.906 ms.) | 0 | 00:01:01.466 ( 61466.906 ms.) | 00:01:13.547( 73547.521 ms.) | 0 | 00:01:13.547( 73547.521 ms.) | 00:01:25.628( 85628.136 ms.) | 0 | 00:01:25.628( 85628.136 ms.) | 00:01:37.708 ( 97708.751 ms.) | 4 | 00:01:37.708 ( 97708.751 ms.) | 00:01:49.789( 109789.366 ms.) | 2 | 00:01:49.789( 109789.366 ms.) | 00:02:01.869( 121869.981 ms.) | 0

ТОП10 снимки по барање во секунда

Барања

--pg_qps.sql
--Calculate Query Per Second 
CREATE OR REPLACE FUNCTION pg_qps( pg_stat_history_id integer ) RETURNS double precision AS $$
DECLARE
 pg_stat_history_rec record ;
 prev_pg_stat_history_id integer ;
 prev_pg_stat_history_rec record;
 total_seconds double precision ;
 result double precision;
BEGIN 
  result = 0 ;
  
  SELECT *
  INTO pg_stat_history_rec
  FROM 
    pg_stat_history
  WHERE id = pg_stat_history_id ;

  IF pg_stat_history_rec.snapshot_timestamp IS NULL 
  THEN
    RAISE EXCEPTION 'ERROR - Not found pg_stat_history for id = %',pg_stat_history_id;
  END IF ;  
  
 --RAISE NOTICE 'pg_stat_history_id = % , snapshot_timestamp = %', pg_stat_history_id , 
 pg_stat_history_rec.snapshot_timestamp ;
  
  SELECT 
    MAX(id)   
  INTO
    prev_pg_stat_history_id
  FROM
    pg_stat_history
  WHERE 
    database_id = pg_stat_history_rec.database_id AND
	queryid IS NULL AND
	id < pg_stat_history_rec.id ;

  IF prev_pg_stat_history_id IS NULL 
  THEN
    RAISE NOTICE 'Not found previous pg_stat_history shapshot for id = %',pg_stat_history_id;
	RETURN NULL ;
  END IF;
  
  SELECT *
  INTO prev_pg_stat_history_rec
  FROM 
    pg_stat_history
  WHERE id = prev_pg_stat_history_id ;
  
  --RAISE NOTICE 'prev_pg_stat_history_id = % , prev_snapshot_timestamp = %', prev_pg_stat_history_id , prev_pg_stat_history_rec.snapshot_timestamp ;    

  total_seconds = extract(epoch from ( pg_stat_history_rec.snapshot_timestamp - prev_pg_stat_history_rec.snapshot_timestamp ));
  
  --RAISE NOTICE 'total_seconds = % ', total_seconds ;    
  
  --RAISE NOTICE 'calls = % ', pg_stat_history_rec.calls ;      
  
  IF total_seconds > 0 
  THEN
    result = pg_stat_history_rec.calls / total_seconds ;
  ELSE
   result = 0 ; 
  END IF;
   
 RETURN result ;
END
$$ LANGUAGE plpgsql;


SELECT 
  id , 
  snapshot_timestamp ,
  calls , 	
  total_time , 
  ( select pg_qps( id )) AS QPS ,
  blk_read_time ,
  blk_write_time
FROM 
  pg_stat_history
WHERE 
  queryid IS NULL AND 
  database_id = DATABASE_ID  AND
  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT AND
  ( select pg_qps( id )) IS NOT NULL 
ORDER BY 5 DESC 
LIMIT 10
|------------------------------------------------ --------------------------------------------- | ТОП10 снимки подредени по QueryPerSeconds броеви -------------------------------------------- ------------------------------------------------- ------------------------------------------------- | #| слика| ИД на слика| повици| вкупно dbtime| QPS| Време на влез/излез| I/O време % +-----+---------------------------------------- ----+---------------------------------+----------- -+------------------------+----------- | 1| 04.04.2019 20:04| 4161| 5758631| 00:06:30.513( 390513.926 ms.)| 1573.396| 00:00:01.470( 1470.110 ms.)| .376 | 2| 04.04.2019 17:00 часот| 4149| 3529197| 00:11:48.830( 708830.618 ms.)| 980.332| 00:12:47.834( 767834.052 ms.)| 108.324 | 3| 04.04.2019 16:00 часот| 4143| 3525360| 00:10:13.492( 613492.351 ms.)| 979.267| 00:08:41.396( 521396.555 ms.)| 84.988 | 4| 04.04.2019 21:03| 4163| 2781536| 00:03:06.470( 186470.979 ms.)| 785.745| 00:00:00.249( 249.865 ms.)| .134 | 5| 04.04.2019 19:03| 4159| 2890362| 00:03:16.784( 196784.755 ms.)| 776.979| 00:00:01.441( 1441.386 ms.)| .732 | 6| 04.04.2019 14:00 часот| 4137| 2397326| 00:04:43.033( 283033.854 ms.)| 665.924| 00:00:00.024(24.505 ms.)| .009 | 7| 04.04.2019 15:00 часот| 4139| 2394416| 00:04:51.435( 291435.010 ms.)| 665.116| 00:00:12.025( 12025.895 ms.)| 4.126 | 8| 04.04.2019 13:00| 4135| 2373043| 00:04:26.791 ( 266791.988 ms.)| 659.179| 00:00:00.064( 64.261 ms.)| .024 | 9| 05.04.2019 01:03| 4167| 4387191| 00:06:51.380( 411380.293 ms.)| 609.332| 00:05:18.847( 318847.407 ms.)| 77.507 | 10| 04.04.2019 18:01| 4157| 1145596| 00:01:19.217( 79217.372 ms.)| 313.004| 00:00:01.319( 1319.676 ms.)| 1.666

Часовна историја на извршување со QueryPerSeconds и В/О време

Барање

SELECT 
  id , 
  snapshot_timestamp ,
  calls , 	
  total_time , 
  ( select pg_qps( id )) AS QPS ,
  blk_read_time ,
  blk_write_time
FROM 
  pg_stat_history
WHERE 
  queryid IS NULL AND 
  database_id = DATABASE_ID  AND
  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT
ORDER BY 2
|-----------------------------------------------------------------------------------------------
| HOURLY EXECUTION HISTORY  WITH QueryPerSeconds and I/O Time
-----------------------------------------------------------------------------------------------------------------------------------------------
| QUERY PER SECOND HISTORY
|    #|          snapshot| snapshotID|      calls|                      total dbtime|        QPS|                          I/O time| I/O time %
+-----+------------------+-----------+-----------+----------------------------------+-----------+----------------------------------+-----------
|    1|  04.04.2019 11:00|       4131|       3747|  00:00:00.835(       835.374 ms.)|      1.041|  00:00:00.000(          .000 ms.)|       .000
|    2|  04.04.2019 12:00|       4133|    1002722|  00:01:52.419(    112419.376 ms.)|    278.534|  00:00:00.149(       149.105 ms.)|       .133
|    3|  04.04.2019 13:00|       4135|    2373043|  00:04:26.791(    266791.988 ms.)|    659.179|  00:00:00.064(        64.261 ms.)|       .024
|    4|  04.04.2019 14:00|       4137|    2397326|  00:04:43.033(    283033.854 ms.)|    665.924|  00:00:00.024(        24.505 ms.)|       .009
|    5|  04.04.2019 15:00|       4139|    2394416|  00:04:51.435(    291435.010 ms.)|    665.116|  00:00:12.025(     12025.895 ms.)|      4.126
|    6|  04.04.2019 16:00|       4143|    3525360|  00:10:13.492(    613492.351 ms.)|    979.267|  00:08:41.396(    521396.555 ms.)|     84.988
|    7|  04.04.2019 17:00|       4149|    3529197|  00:11:48.830(    708830.618 ms.)|    980.332|  00:12:47.834(    767834.052 ms.)|    108.324
|    8|  04.04.2019 18:01|       4157|    1145596|  00:01:19.217(     79217.372 ms.)|    313.004|  00:00:01.319(      1319.676 ms.)|      1.666
|    9|  04.04.2019 19:03|       4159|    2890362|  00:03:16.784(    196784.755 ms.)|    776.979|  00:00:01.441(      1441.386 ms.)|       .732
|   10|  04.04.2019 20:04|       4161|    5758631|  00:06:30.513(    390513.926 ms.)|   1573.396|  00:00:01.470(      1470.110 ms.)|       .376
|   11|  04.04.2019 21:03|       4163|    2781536|  00:03:06.470(    186470.979 ms.)|    785.745|  00:00:00.249(       249.865 ms.)|       .134
|   12|  04.04.2019 23:03|       4165|    1443155|  00:01:34.467(     94467.539 ms.)|    200.438|  00:00:00.015(        15.287 ms.)|       .016
|   13|  05.04.2019 01:03|       4167|    4387191|  00:06:51.380(    411380.293 ms.)|    609.332|  00:05:18.847(    318847.407 ms.)|     77.507
|   14|  05.04.2019 02:03|       4171|     189852|  00:00:10.989(     10989.899 ms.)|     52.737|  00:00:00.539(       539.110 ms.)|      4.906
|   15|  05.04.2019 03:01|       4173|       3627|  00:00:00.103(       103.000 ms.)|      1.042|  00:00:00.004(         4.131 ms.)|      4.010
|   16|  05.04.2019 04:00|       4175|       3627|  00:00:00.085(        85.235 ms.)|      1.025|  00:00:00.003(         3.811 ms.)|      4.471
|   17|  05.04.2019 05:00|       4177|       3747|  00:00:00.849(       849.454 ms.)|      1.041|  00:00:00.006(         6.124 ms.)|       .721
|   18|  05.04.2019 06:00|       4179|       3747|  00:00:00.849(       849.561 ms.)|      1.041|  00:00:00.000(          .051 ms.)|       .006
|   19|  05.04.2019 07:00|       4181|       3747|  00:00:00.839(       839.416 ms.)|      1.041|  00:00:00.000(          .062 ms.)|       .007
|   20|  05.04.2019 08:00|       4183|       3747|  00:00:00.846(       846.382 ms.)|      1.041|  00:00:00.000(          .007 ms.)|       .001
|   21|  05.04.2019 09:00|       4185|       3747|  00:00:00.855(       855.426 ms.)|      1.041|  00:00:00.000(          .065 ms.)|       .008
|   22|  05.04.2019 10:00|       4187|       3797|  00:01:40.150(    100150.165 ms.)|      1.055|  00:00:21.845(     21845.217 ms.)|     21.812

Текст на сите SQL-селектирања

Барање

SELECT 
  queryid , 
  query 
FROM 
  pg_stat_history
WHERE 
  queryid IS NOT NULL AND 
  database_id = DATABASE_ID  AND
  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT
GROUP BY queryid , query

Вкупно

Како што можете да видите, користејќи прилично едноставни средства, можете да добиете многу корисни информации за обемот на работа и состојбата на базата на податоци.

Забелешка:Ако го снимаме прашалникот во прашања, ќе ја добиеме историјата за посебно барање (за да заштедиме простор, извештаите за посебно барање се испуштени).

Значи, статистичките податоци за перформансите на барањето се достапни и собрани.
Првата фаза „собирање на статистички податоци“ е завршена.

Можете да преминете на втората фаза - „поставување метрика за изведба“.
Следење на перформансите на барањето PostgreSQL. Дел 1 - известување

Но, тоа е сосема друга приказна.

Да се ​​продолжи ...

Извор: www.habr.com

Додадете коментар