Monitorimi i performancës së pyetjeve të PostgreSQL. Pjesa 1 - raportimi

Inxhinier - përkthyer nga latinishtja - i frymëzuar.
Një inxhinier mund të bëjë gjithçka. (c) R. Diesel.
Epigrafe.
Monitorimi i performancës së pyetjeve të PostgreSQL. Pjesa 1 - raportimi
Ose një histori se pse një administrator i bazës së të dhënave duhet të kujtojë të kaluarën e tij programuese.

Parathënie libri

Të gjithë emrat janë ndryshuar. Koincidencat janë të rastësishme. Materiali përfaqëson vetëm mendimin personal të autorit.

Mohimi i garancive: Seria e planifikuar e artikujve nuk do të përmbajë një përshkrim të detajuar dhe të saktë të tabelave dhe skripteve të përdorura. Materialet nuk mund të përdoren menjëherë “SI ËSHTË”.
Së pari, për shkak të vëllimit të madh të materialit,
së dyti, për shkak të marrëdhënies së ngushtë me bazën e prodhimit të një klienti të vërtetë.
Prandaj, artikujt do të përmbajnë vetëm ide dhe përshkrime në formën më të përgjithshme.
Ndoshta në të ardhmen sistemi do të rritet në nivelin e postimit në GitHub, ose ndoshta jo. Koha do të tregojë.

Fillimi i tregimit - "A ju kujtohet se si filloi gjithçka'.
Çfarë ndodhi si rezultat, në termat më të përgjithshëm - "Sinteza si një nga metodat për përmirësimin e performancës PostgreSQL»

Pse më duhen të gjitha këto?

Epo, së pari, për të mos harruar, duke kujtuar ditët e lavdishme të pensionit.
Së dyti, për të sistemuar atë që u shkrua. Sepse ndonjëherë filloj të hutohem dhe harroj disa pjesë.

Epo, dhe gjëja më e rëndësishme është se mund të jetë e dobishme për dikë dhe t'i ndihmojë ata të shmangin rishpikjen e timonit dhe të mos mbledhin një grabujë. Me fjalë të tjera, përmirësoni karmën tuaj (jo të Khabrov). Sepse gjëja më e vlefshme në këtë botë janë idetë. Gjëja kryesore është të gjesh një ide. Por shndërrimi i një ideje në realitet është një çështje thjesht teknike.

Pra, le të fillojmë, pak nga pak ...

Formulimi i problemit.

Në dispozicion:

Baza e të dhënave PostgreSQL(10.5), lloji i ngarkesës së përzier (OLTP+DSS), ngarkesë mesatare, e vendosur në renë AWS.
Nuk ka monitorim të bazës së të dhënave; monitorimi i infrastrukturës ofrohet në formën e mjeteve standarde AWS në një konfigurim minimal.

Kërkohet:

Monitoroni performancën dhe statusin e bazës së të dhënave, gjeni dhe keni informacion fillestar për optimizimin e pyetjeve të rënda të bazës së të dhënave.

Prezantim ose analizë e shkurtër e opsioneve të zgjidhjes

Për të filluar, le të përpiqemi të analizojmë opsionet për zgjidhjen e problemit nga pikëpamja e një analize krahasuese të përfitimeve dhe disavantazheve për inxhinierin, dhe le të merren me përfitimet dhe ata që kanë të drejtë sipas orarit të personelit. humbjet e menaxhimit.

Opsioni 1 - "Puna sipas kërkesës"

Ne lëmë gjithçka ashtu siç është. Nëse klienti nuk është i kënaqur me diçka në funksionalitetin, performancën e bazës së të dhënave ose aplikacionit, ai do të njoftojë inxhinierët e DBA me e-mail ose duke krijuar një incident në tabaka e biletave.
Inxhinieri, pasi të ketë marrë njoftimin, do ta kuptojë problemin, do të ofrojë një zgjidhje ose do ta vendosë problemin në pjesën e pasme, duke shpresuar se gjithçka do të zgjidhet vetë dhe gjithsesi, gjithçka do të harrohet së shpejti.
Gingerbread dhe donuts, mavijosje dhe gungaBukë me xhenxhefil dhe donuts:
1. Nuk ka nevojë të bëni asgjë shtesë.
2. Gjithmonë ekziston mundësia për të bërë justifikime dhe për të dështuar.
3. Shumë kohë që mund ta shpenzoni sipas gjykimit tuaj.
Mavijosje dhe gunga:
1. Herët a vonë, klienti do të mendojë për thelbin e ekzistencës dhe drejtësisë universale në këtë botë dhe do t'i bëjë edhe një herë vetes pyetjen - pse po i paguaj paratë e mia? Pasoja është gjithmonë e njëjtë - pyetja e vetme është kur klienti do të mërzitet dhe do të përshëndesë me dorë. Dhe ushqyesi do të jetë bosh. Është e trishtueshme.
2. Zhvillimi i inxhinierit - zero.
3. Vështirësi në planifikimin e punës dhe ngarkimit

Opsioni 2- "Vallëzimi me dajre, avullimi dhe veshja e këpucëve"

Paragrafi 1-Pse na duhet një sistem monitorimi, çdo gjë do ta marrim me kërkesa. Ne drejtojmë një grup të të gjitha llojeve të pyetjeve në fjalorin e të dhënave dhe pamjet dinamike, aktivizojmë të gjitha llojet e numëruesve, vendosim gjithçka në tabela dhe analizojmë periodikisht listat dhe tabelat. Si rrjedhojë kemi grafikë, tabela, raporte të bukura ose jo aq të bukura. Gjëja kryesore është të kesh më shumë, më shumë.
Paragrafi 2-Ne gjenerojmë aktivitet dhe nisim analizën e gjithë kësaj.
Paragrafi 3-Ne po përgatisim një dokument të caktuar, këtë dokument e quajmë thjesht - “si duhet të krijojmë një bazë të dhënash”.
Paragrafi 4-Klienti, duke parë gjithë këtë shkëlqim grafikësh dhe numrash, është në një besim fëminor, naiv - tani gjithçka do të funksionojë për ne, së shpejti. Dhe, ai ndahet lehtësisht dhe pa dhimbje nga burimet e tij financiare. Menaxhmenti është gjithashtu i bindur se inxhinierët tanë punojnë mirë. Ngarkimi në maksimum.
Paragrafi 5-Përsëriteni rregullisht hapin 1.
Gingerbread dhe donuts, mavijosje dhe gungaBukë me xhenxhefil dhe donuts:
1. Jeta e menaxherëve dhe inxhinierëve është e thjeshtë, e parashikueshme dhe e mbushur me aktivitet. Gjithçka po gumëzhin, të gjithë janë të zënë.
2. Jeta e klientit gjithashtu nuk është e keqe - ai është gjithmonë i sigurt se ai thjesht duhet të jetë pak i duruar dhe gjithçka do të funksionojë. Nuk po bëhet më mirë, mirë, bota është e padrejtë, në jetën tjetër do të keni fat.
Mavijosje dhe gunga:
1. Herët a vonë, do të ketë një ofrues më të shpejtë të një shërbimi të ngjashëm që do të bëjë të njëjtën gjë, por pak më lirë. Dhe nëse rezultati është i njëjtë, pse të paguani më shumë. E cila përsëri do të çojë në zhdukjen e ushqyesit.
2. Është e mërzitshme. Sa i mërzitshëm është çdo aktivitet i pakuptimtë.
3. Si në versionin e mëparshëm, nuk ka zhvillim. Por për një inxhinier, e keqja është se, ndryshe nga opsioni i parë, ju duhet të gjeneroni vazhdimisht një IBD. Dhe kjo kërkon kohë. Të cilat mund t'i shpenzoni për të mirën e të dashurit tuaj. Për shkak se ju nuk mund të kujdeseni për veten tuaj, askush nuk ju shqetëson.

Opsioni 3 - Ju nuk keni nevojë të shpikni një biçikletë, ju vetëm duhet ta blini atë dhe ta hipni atë.

Jo më kot inxhinierët e kompanive të tjera hanë pica me birrë (oh, ditët e lavdisë së Shën Petersburgut në vitet '90). Le të përdorim sistemet e monitorimit që janë bërë, korrigjohen dhe funksionojnë, dhe në përgjithësi do të përfitojnë (mirë, të paktën për krijuesit e tyre).
Gingerbread dhe donuts, mavijosje dhe gungaBukë me xhenxhefil dhe donuts:
1. Nuk ka nevojë të humbni kohë për të gjetur diçka që tashmë është shpikur. Merrni atë dhe përdorni atë.
2. Sistemet e monitorimit nuk janë të shkruara nga budallenjtë dhe ato, natyrisht, janë të dobishme.
3. Sistemet e monitorimit të punës zakonisht ofrojnë informacion të dobishëm të filtruar.
Mavijosje dhe gunga:
1. Inxhinieri në këtë rast nuk është inxhinier, por thjesht përdorues i produktit të dikujt tjetër ose përdorues.
2. Klienti duhet të bindet për nevojën për të blerë diçka që, në përgjithësi, nuk dëshiron ta kuptojë dhe nuk duhet ta kuptojë dhe në përgjithësi buxheti i vitit është miratuar dhe nuk do të ndryshojë. Pastaj ju duhet të ndani një burim të veçantë dhe ta konfiguroni atë për një sistem specifik. Ato. së pari ju duhet të paguani, paguani dhe paguani përsëri. Dhe klienti është dorështrënguar. Kjo është norma e kësaj jete.

Çfarë të bëni - Chernyshevsky? Pyetja juaj është shumë me vend. (Me)

Në këtë rast të veçantë dhe situatën aktuale, ju mund ta bëni atë pak më ndryshe - le të bëjmë sistemin tonë të monitorimit.
Monitorimi i performancës së pyetjeve të PostgreSQL. Pjesa 1 - raportimi
Epo, jo një sistem, natyrisht, në kuptimin e plotë të fjalës, që është shumë i zhurmshëm dhe mendjemadh, por të paktën disi e lehtëson detyrën tuaj dhe mbledh më shumë informacion për të zgjidhur incidentet e performancës. Për të mos e gjetur veten në një situatë - "shko atje, nuk e di ku, gjej diçka, nuk e di çfarë."

Cilat janë të mirat dhe të këqijat e këtij opsioni:

Pro:
1. Kjo është interesante. Epo, të paktën është më interesante sesa konstante "tkurrja e skedarit të të dhënave, ndryshimi i hapësirës së tabelës, etj."
2. Këto janë aftësi të reja dhe zhvillim të ri. Të cilat, herët a vonë, do t'ju japin bukë me xhenxhefil dhe donut të merituar.
Cons:
1. Do t'ju duhet të punoni. Punoni shumë.
2. Do t'ju duhet të shpjegoni rregullisht kuptimin dhe perspektivat e të gjitha aktiviteteve.
3. Diçka do të duhet të sakrifikohet, sepse i vetmi burim në dispozicion të një inxhinieri - koha - është i kufizuar nga Universi.
4. Gjëja më e keqe dhe më e pakëndshme - rezultati mund të jetë budallallëk si "Jo një mi, jo një bretkocë, por një kafshë e panjohur".

Ata që nuk rrezikojnë nuk pinë shampanjë.
Pra - fillon argëtimi.

Ideja e përgjithshme - në mënyrë skematike

Monitorimi i performancës së pyetjeve të PostgreSQL. Pjesa 1 - raportimi
(Ilustrimi i marrë nga artikulli «Sinteza si një nga metodat për përmirësimin e performancës PostgreSQL")

Shpjegim:

  • Shtesa standarde PostgreSQL "pg_stat_statements" është instaluar në bazën e të dhënave të synuar.
  • Në bazën e të dhënave të monitorimit, ne krijojmë një grup tabelash shërbimi për ruajtjen e historisë së pg_stat_statements në fazën fillestare dhe për vendosjen e metrikës dhe monitorimit në të ardhmen
  • Në hostin e monitorimit, ne krijojmë një grup skriptesh bash, duke përfshirë ato për gjenerimin e incidenteve në sistemin e biletave.

Tabelat e shërbimit

Së pari, një ERD e thjeshtuar skematike, çfarë ndodhi në fund:
Monitorimi i performancës së pyetjeve të PostgreSQL. Pjesa 1 - raportimi
Përshkrimi i shkurtër i tabelavepika e fundit - host, pika e lidhjes me shembullin
bazës së të dhënave - parametrat e bazës së të dhënave
pg_stat_histori - një tabelë historike për ruajtjen e fotografive të përkohshme të pamjes pg_stat_statements të bazës së të dhënave të synuar
fjalor metrikë - fjalor i matjeve të performancës
konfigurim_metrik — konfigurimi i metrikës individuale
metrik — një metrikë specifike për kërkesën që po monitorohet
historia e alarmit metrik - historia e paralajmërimeve të performancës
log_query — një tabelë shërbimi për ruajtjen e të dhënave të analizuara nga një skedar log PostgreSQL i shkarkuar nga AWS
bazë — parametrat e periudhave kohore të përdorura si bazë
pikë kontrolli — konfigurimi i metrikës për kontrollimin e statusit të bazës së të dhënave
pikë kontrolli_histori_alarmi — historia paralajmëruese e matjeve të kontrollit shëndetësor të bazës së të dhënave
pg_stat_db_queries — tabela e shërbimit të kërkesave aktive
regjistri i aktivitetit — Tabela e shërbimit të regjistrit të aktiviteteve
trap_oid — Tabela e shërbimit të konfigurimit të kurthit

Faza 1 - mbledhni informacion statistikor për performancën dhe merrni raporte

Një tabelë përdoret për të ruajtur informacionin statistikor pg_stat_histori
Struktura e tabelës pg_stat_history

                                          Tabela "public.pg_stat_history" Kolona | Lloji | Modifikuesit------------------------------------------------- -+------------------------------------------ id | numër i plotë | jo null e paracaktuar nextval('pg_stat_history_id_seq'::regclass) snapshot_timestamp | vula kohore pa zonë kohore | data_id | numër i plotë | dbid | oid | userid | oid | pyetësor | bigint | pyetje | teksti | thirrjet | bigint | koha_gjithsej | saktësi të dyfishtë | koha_min | saktësi të dyfishtë | koha_maksimumi | saktësi të dyfishtë | koha_mesatare | saktësi të dyfishtë | stddev_time | saktësi të dyfishtë | rreshtat | bigint | shared_blks_hit | bigint | shared_blks_lexuar | bigint | shared_blks_dirtied | bigint | shared_blks_written | bigint | lokal_blks_hit | bigint | lokale_blks_lexuar | bigint | lokale_blks_ndotur | bigint | lokale_blks_shkruar | bigint | temp_blks_lexuar | bigint | temp_blks_shkruar | bigint | blk_koha_leximi | saktësi të dyfishtë | blk_write_time | saktësi të dyfishtë | ID_bazë | numër i plotë | Indekset: "pg_stat_history_pkey" ÇELËSI PRIMARY, btree (id) "database_idx" btree (database_id) "queryid_idx" btree (queryid) "snapshot_timestamp_idx" btree (snapshot_timestamp) "Foreign_timestamp" Baza e të dhënave REFERENCAT (id ) NË FSHIJE KASKADËN

Siç mund ta shihni, tabela është vetëm të dhënat kumulative të pamjes pg_stat_statements në bazën e të dhënave të synuar.

Përdorimi i kësaj tabele është shumë i thjeshtë

pg_stat_histori do të përfaqësojë statistikat e grumbulluara të ekzekutimit të pyetjeve për çdo orë. Në fillim të çdo ore, pas plotësimit të tabelës, statistikat pg_stat_statements rivendosur me pg_stat_statements_reset ().
Shenim: Statistikat mblidhen për pyetje me kohëzgjatje ekzekutimi më shumë se 1 sekondë.
Popullimi i tabelës 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;

Si rezultat, pas një periudhe kohe në tabelë pg_stat_histori do të kemi një grup fotografish të përmbajtjes së tabelës pg_stat_statements bazën e të dhënave të synuar.

Në fakt raportimi

Duke përdorur pyetje të thjeshta, mund të merrni raporte mjaft të dobishme dhe interesante.

Të dhënat e grumbulluara për një periudhë të caktuar kohe

hetim

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 ;

Koha DB

to_char(intervali '1 milisekonda' * pg_total_stat_history_rec.total_time, 'HH24:MI:SS.MS')

Koha e hyrjes/daljes

to_char(intervali '1 milisekonda' * ( pg_total_stat_history_rec.blk_read_time + pg_total_stat_history_rec.blk_write_time ), 'HH24:MI:SS.MS')

TOP10 SQL sipas total_time

hetim

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
-------------------------------------------------- ----------------------------------- | TOP10 SQL SIPAS KOHËS TOTALE TË EKZEKUTIMIT | #| pyetësor| thirrjet| thërret %| koha_gjithsej (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 sipas kohës totale të hyrjes/daljes

hetim

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
-------------------------------------------------- -------------------------------------- | TOP10 SQL NGA KOHA TOTALE I/DAL | #| pyetësor| thirrjet| thërret %| Koha e hyrjes/daljes (ms)|db koha e hyrjes/daljes % +----+-----------+-----------+------ -----------+--------------------------------------- ------ -- | 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 sipas kohës maksimale të ekzekutimit

hetim

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

-------------------------------------------------- --------------------------------------- | TOP10 SQL NGA KOHËN MAX EKZEKUTIMI | #| pamje e çastit| snapshot ID| pyetësor| koha_max (ms) +----+----------------------------------------- --+--------------------------------------- | 1| 05.04.2019/01/03 4169:655729273| 00| 02| 01.869:121869.981:2 ( 04.04.2019 ms.) | 17| 00/4153/821760255 00:01| 41.570| 101570.841| 3:04.04.2019:16 ( 00 ms.) | 4146| 821760255/00/01 41.570:101570.841| 4| 04.04.2019| 16:00:4144 ( 4152624390 ms.) | 00| 01/36.964/96964.607 5:04.04.2019| 17| 00| 4151:4152624390:00(01 ms.) | 36.964| 96964.607/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:8 ( 04.04.2019 ms.) | 15| 00/4140/1484454471 00:00| 11.892| 11892.302| 9:04.04.2019:16(00 ms.) | 4145| 1484454471/00/00 11.892:11892.302| 10| 04.04.2019| 17:00:4152 ( 1484454471 ms.) | 00| 00/11.892/11892.302 XNUMX:XNUMX| XNUMX| XNUMX| XNUMX:XNUMX:XNUMX ( XNUMX ms.) | XNUMX| XNUMX/XNUMX/XNUMX XNUMX:XNUMX| XNUMX| XNUMX| XNUMX:XNUMX:XNUMX ( XNUMX ms.)

TOP10 SQL nga SHARED buffer leximi/shkrimi

hetim

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
-------------------------------------------------- ------------------------------------------ | TOP10 SQL NGA BUFERI I NDAJTËR LEXO/SHKRUAR | #| foto e çastit| snapshot ID| pyetësor| blloqe të përbashkëta të lexuara| blloqet e përbashkëta shkruajnë +----+----------------------------------------- -+------------------------------------------- | 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 | XNUMX| XNUMX/XNUMX/XNUMX XNUMX:XNUMX| XNUMX| XNUMX| XNUMX| XNUMX | XNUMX| XNUMX/XNUMX/XNUMX XNUMX:XNUMX| XNUMX| XNUMX| XNUMX| XNUMX ------------------------------------------------- -------------------------------------------

Histogrami i shpërndarjes së kërkesave sipas kohës maksimale të ekzekutimit

Kërkesat

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 ) ;
|------------------------------------------------ --------------------------------------------- | HISTOGRAM MAX_TIME | TOTALI I THIRAT: 33851920 | MIN KOHA: 00:00:01.063 | KOHA MAX: 00:02:01.869 ----------------------------------------------------------------------- --------------------------------------- | min kohëzgjatja| kohëzgjatja maksimale| thirrje +---------------------------------+-------------- ---------------------+---------- | 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

TOP10 fotografitë e çastit sipas pyetjes për sekondë

Kërkesat

--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
|------------------------------------------------ --------------------------------------------- | TOP10 fotografitë e renditura sipas numrave QueryPerSeconds -------------------------------------------- -------------------------------------------------- ------------------------------------------------ | #| pamje e çastit| snapshot ID| thirrjet| koha totale db| QPS| Koha e hyrjes/daljes| Koha e hyrjes/daljes % +-----+--------------------------------------- ----+--------------------------------------------- -+------------------------------------ | 1| 04.04.2019/20/04 4161:5758631| 00| 06| 30.513:390513.926:1573.396( 00 ms.)| 00| 01.470:1470.110:376( 2 ms.)| .04.04.2019 | 17| 00/4149/3529197 00:11| 48.830| 708830.618| 980.332:00:12( 47.834 ms.)| 767834.052| 108.324:3:04.04.2019( 16 ms.)| 00 | 4143| 3525360/00/10 13.492:613492.351| 979.267| 00| 08:41.396:521396.555( 84.988 ms.)| 4| 04.04.2019:21:03(4163 ms.)| 2781536 | 00| 03/06.470/186470.979 785.745:00| 00| 00.249| 249.865:134:5( 04.04.2019 ms.)| 19| 03:4159:2890362( 00 ms.)| .03 | 16.784| 196784.755 776.979:00| 00| 01.441| 1441.386:732:6( 04.04.2019 ms.)| 14| 00:4137:2397326( 00 ms.)| .04 | 43.033| 283033.854/665.924/00 00:00.024| 24.505| 009| 7:04.04.2019:15( 00 ms.)| 4139| 2394416:00:04(51.435 ms.)| .291435.010 | 665.116| 00/00/12.025 12025.895:4.126| 8| 04.04.2019| 13:00:4135( 2373043 ms.)| 00| 04:26.791:266791.988( 659.179 ms.)| 00 | 00| 00.064 64.261:024| 9| 05.04.2019| 01:03:4167 ( 4387191 ms.)| 00| 06:51.380:411380.293( 609.332 ms.)| .00 | 05| 18.847/318847.407/77.507 10:04.04.2019| 18| 01| 4157:1145596:00( 01 ms.)| 19.217| 79217.372:313.004:00( 00 ms.)| 01.319 | 1319.676| 1.666/XNUMX/XNUMX XNUMX:XNUMX| XNUMX| XNUMX| XNUMX:XNUMX:XNUMX( XNUMX ms.)| XNUMX| XNUMX:XNUMX:XNUMX( XNUMX ms.)| XNUMX

Historia e ekzekutimit për orë me QueryPerSeconds dhe Koha I/O

hetim

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

Teksti i të gjitha përzgjedhjeve SQL

hetim

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

Total

Siç mund ta shihni, duke përdorur mjete mjaft të thjeshta, mund të merrni shumë informacione të dobishme në lidhje me ngarkesën e punës dhe gjendjen e bazës së të dhënave.

Shënim:Nëse e regjistrojmë pyetësorin në pyetje, do të marrim historikun për një pyetje të veçantë (për të kursyer hapësirë, raportet për një pyetje të veçantë janë hequr).

Pra, të dhënat statistikore mbi performancën e pyetjeve janë të disponueshme dhe të mbledhura.
Ka përfunduar faza e parë “mbledhja e të dhënave statistikore”.

Mund të kaloni në fazën e dytë - "konfigurimi i matjeve të performancës".
Monitorimi i performancës së pyetjeve të PostgreSQL. Pjesa 1 - raportimi

Por kjo është një histori krejt tjetër.

Vazhdon…

Burimi: www.habr.com

Shto një koment