Efikecmonitorado de PostgreSQL-demandoj. Parto 1 - raportado

Inĝeniero - tradukita el la latina - inspirita.
Inĝeniero povas fari ion ajn. (c) R. Diesel.
Epigrafoj.
Efikecmonitorado de PostgreSQL-demandoj. Parto 1 - raportado
Aŭ rakonto pri kial datumbaza administranto bezonas memori sian programan pasintecon.

Antaŭparolo

Ĉiuj nomoj estis ŝanĝitaj. Matĉoj estas hazardaj. La materialo estas nur la persona opinio de la aŭtoro.

Malgarantio pri garantioj: en la planita serio de artikoloj ne estos detala kaj preciza priskribo de la uzataj tabeloj kaj skriptoj. Materialoj ne povas esti tuj uzataj "TIAL".
Unue, pro la granda kvanto da materialo,
due, pro la akreco kun la produktada bazo de vera kliento.
Tial, nur ideoj kaj priskriboj en la plej ĝenerala formo estos donitaj en la artikoloj.
Eble estonte la sistemo kreskos al la nivelo de afiŝado sur GitHub, aŭ eble ne. La tempo montros.

La komenco de la rakonto -Ĉu vi memoras, kiel ĉio komenciĝis".
Kio okazis kiel rezulto, en la plej ĝeneralaj terminoj - "Sintezo kiel unu el la metodoj por plibonigi la agadon de PostgreSQL»

Kial mi bezonas ĉion ĉi?

Nu, unue, por ne forgesi vin mem, memorante la glorajn tagojn en emeritiĝo.
Due, sistemigi tion, kio estis skribita. Por jam mi, foje mi komencas konfuziĝi kaj forgesi apartajn partojn.

Nu, kaj plej grave - subite ĝi povas esti utila por iu kaj helpi ne reinventi la radon kaj ne kolekti rastilon. Alivorte, plibonigu vian karmon (ne Khabrovsky). Ĉar la plej valora afero en ĉi tiu mondo estas ideoj. La ĉefa afero estas trovi ideon. Kaj traduki la ideon en realecon jam estas pure teknika afero.

Do ni komencu malrapide...

Formulo de la problemo.

Disponebla:

PostgreSQL (10.5), miksita ŝarĝo (OLTP+DSS), meza ĝis malpeza ŝarĝo, gastigita en la AWS-nubo.
Ne ekzistas datumbaza monitorado, infrastruktura monitorado estas prezentita kiel normaj AWS-iloj en minimuma agordo.

Bezonata:

Monitoru la agadon kaj staton de la datumbazo, trovu kaj havu komencajn informojn por optimumigi pezajn datumbazajn demandojn.

Mallonga enkonduko aŭ analizo de solvoj

Komence, ni provu analizi la eblojn por solvi la problemon el la vidpunkto de kompara analizo de la avantaĝoj kaj problemoj por la inĝeniero, kaj lasu tiujn, kiuj supozeble estas en la persona listo, trakti la avantaĝojn kaj perdojn. de administrado.

Opcio 1 - "Laborante laŭpeto"

Ni lasas ĉion kiel ĝi estas. Se la kliento ne kontentas pri io en la sano, agado de la datumbazo aŭ aplikaĵo, li sciigos la DBA-inĝenierojn per retpoŝto aŭ kreante okazaĵon en la biletujo.
Inĝeniero, ricevinte sciigon, komprenos la problemon, proponos solvon aŭ arkivos la problemon, esperante, ke ĉio solvos sin, kaj ĉiuokaze, ĉio baldaŭ estos forgesita.
Zingibra pano kaj benkoj, kontuziĝoj kaj tuberojZingibra pano kaj benkoj:
1. Nenio kroma fari
2. Ĉiam estas la ŝanco eliri kaj malpuriĝi.
3. Multan tempon, kiun vi povas elspezi memstare.
Kontuzo kaj tuberoj:
1. Pli aŭ malpli frue, la kliento pensos pri la esenco de esti kaj universala justeco en ĉi tiu mondo kaj denove faros al si la demandon - kial mi pagas al ili mian monon? La sekvo estas ĉiam la sama - la sola demando estas kiam la kliento enuiĝas kaj svingas adiaŭon. Kaj la manĝilo estas malplena. Estas malgaja.
2. La evoluo de inĝeniero estas nula.
3. Malfacilaĵoj en planado de laboro kaj ŝarĝo

Opcio 2 - "Dancu per tamburinoj, surmetu kaj surmetu ŝuojn"

Paragrafo 1-Kial ni bezonas monitoran sistemon, ni ricevos ĉiujn petojn. Ni lanĉas amason da ĉiaj demandoj al la datumvortaro kaj dinamikaj vidoj, ŝaltas ĉiajn nombrilojn, alportas ĉion en tabelojn, periode analizas listojn kaj tabelojn, kvazaŭ. Kiel rezulto, ni havas belajn aŭ ne tre grafikaĵojn, tabelojn, raportojn. La ĉefa afero - tio estus pli, pli.
Paragrafo 2-Generu agadon-kuru la analizon de ĉio ĉi.
Paragrafo 3-Ni preparas certan dokumenton, ni nomas ĉi tiun dokumenton, simple - "kiel ni ekipas la datumbazon."
Paragrafo 4— La kliento, vidante ĉi tiun tutan grandiozecon de grafikaĵoj kaj figuroj, estas en infana naiva konfido — nun ĉio funkcios por ni, baldaŭ. Kaj, facile kaj sendolore disiĝas de siaj financaj rimedoj. Administrado ankaŭ certas, ke niaj inĝenieroj laboras forte. Maksimuma ŝarĝo.
Paragrafo 5- Ripetu la paŝon 1 regule.
Zingibra pano kaj benkoj, kontuziĝoj kaj tuberojZingibra pano kaj benkoj:
1. La vivo de administrantoj kaj inĝenieroj estas simpla, antaŭvidebla kaj plena de agado. Ĉio zumas, ĉiuj estas okupataj.
2. La vivo de la kliento ankaŭ ne estas malbona - li ĉiam certas, ke vi bezonas iom pacienci kaj ĉio funkcios. Ĝi ne pliboniĝas, nu, nu – ĉi tiu mondo estas maljusta, en la venonta vivo – vi estos bonŝanca.
Kontuzo kaj tuberoj:
1. Pli aŭ malpli frue, estos pli inteligenta provizanto de simila servo, kiu faros la samon, sed iom pli malmultekosta. Kaj se la rezulto estas la sama, kial pagi pli. Kiu denove kondukos al la malapero de la nutrilo.
2. Estas enuiga. Kiel enuiga ajna eta signifoplena agado.
3. Kiel en la antaŭa versio - neniu evoluo. Sed por inĝeniero, la minusaĵo estas, ke, male al la unua opcio, ĉi tie vi devas konstante generi IDB. Kaj tio bezonas tempon. Kiu povas esti elspezita por la avantaĝo de via amato. Ĉar vi ne povas zorgi pri vi mem, ĉiuj zorgas pri vi.

Opcio 3-Ne necesas inventi biciklon, vi devas aĉeti ĝin kaj veturi ĝin.

Inĝenieroj de aliaj kompanioj konscie manĝas picon kun biero (ho, la gloraj tempoj de Sankt-Peterburgo en la 90-aj jaroj). Ni uzu monitorajn sistemojn, kiuj estas faritaj, sencimigitaj kaj funkciantaj, kaj ĝenerale ili alportas avantaĝojn (nu, almenaŭ al siaj kreintoj).
Zingibra pano kaj benkoj, kontuziĝoj kaj tuberojZingibra pano kaj benkoj:
1. Ne necesas perdi tempon inventante tion, kio jam estas elpensita. Prenu kaj uzu.
2. Monitorsistemoj ne estas verkitaj de malsaĝuloj, kaj kompreneble ili estas utilaj.
3. Laborantaj monitoraj sistemoj kutime provizas utilajn filtritajn informojn.
Kontuzo kaj tuberoj:
1. La inĝeniero ĉi-kaze ne estas inĝeniero, sed nur uzanto de la produkto de iu alia aŭ uzanto.
2. La kliento devas esti konvinkita pri la bezono aĉeti ion, kion li ĝenerale ne volas kompreni, kaj li ne devus, kaj ĝenerale la buĝeto por la jaro estas aprobita kaj ne ŝanĝiĝos. Tiam vi devas asigni apartan rimedon, agordi ĝin por specifa sistemo. Tiuj. Unue vi devas pagi, pagi kaj pagi denove. Kaj la kliento estas avara. Ĉi tio estas la normo de ĉi tiu vivo.

Kion fari, Ĉerniŝevskij? Via demando estas tre trafa. (Kun)

En ĉi tiu aparta kazo kaj la nuna situacio, vi povas fari iom malsame - ni faru nian propran monitoran sistemon.
Efikecmonitorado de PostgreSQL-demandoj. Parto 1 - raportado
Nu, ne sistemo, kompreneble, en la plena senco de la vorto, ĉi tio estas tro laŭta kaj aroganta, sed almenaŭ iel faciligu al vi mem kaj kolektu pli da informoj por solvi agadojn incidentojn. Por ne trovi vin en situacio - "iru tien, mi ne scias kien, trovu tion, mi ne scias kion."

Kio estas la avantaĝoj kaj malavantaĝoj de ĉi tiu opcio:

Pros:
1. Estas interese. Nu, almenaŭ pli interesa ol la konstanta "malgrandigi datumdosieron, ŝanĝi tabelspacon, ktp."
2. Ĉi tiuj estas novaj kapabloj kaj nova evoluo. Kiu estonte pli aŭ malpli frue donos merititajn zingibrbukojn kaj benkojn.
Kons:
1. Devas labori. Laboru multe.
2. Vi devos regule klarigi la signifon kaj perspektivojn de ĉiu agado.
3. Io devos esti oferita, ĉar la sola rimedo disponebla al la inĝeniero – la tempo – estas limigita de la Universo.
4. La plej malbona kaj plej malagrabla - sekve, rubo kiel "Ne muso, ne rano, sed nekonata besteto" povas rezulti.

Kiu ne riskas ion, ne trinkas ĉampanon.
Do, la amuzo komenciĝas.

Ĝenerala ideo - skema

Efikecmonitorado de PostgreSQL-demandoj. Parto 1 - raportado
(Ilustraĵo prenita el artikolo «Sintezo kiel unu el la metodoj por plibonigi la agadon de PostgreSQL»)

Klarigo:

  • La cela datumbazo estas instalita per la norma etendo de PostgreSQL "pg_stat_statements".
  • En la monitora datumbazo, ni kreas aron da servotabeloj por stoki la pg_stat_statements-historion en la komenca etapo kaj por agordi metrikojn kaj monitoradon estonte.
  • Sur la monitora gastiganto, ni kreas aron da bash-skriptoj, inkluzive de tiuj por generi incidentojn en la biletsistemo.

Servaj tabloj

Komence, skeme simpligita ERD, kio okazis finfine:
Efikecmonitorado de PostgreSQL-demandoj. Parto 1 - raportado
Mallonga priskribo de la tabelojfinpunkto - gastiganto, konektopunkto al la petskribo
DataBase - datumbazaj opcioj
pg_stat_historio - historia tabelo por stoki provizorajn momentfotojn de la pg_stat_statements-vido de la cela datumbazo
metrika_glosaro - Vortaro de agado-metrikoj
metriko_agordo - agordo de individuaj metrikoj
metriko - specifa metriko por la peto, kiu estas monitorita
metrika_alerta_historio - historio de agado-avertoj
log_demando - servotabelo por stoki analizitajn rekordojn de la postgreSQL-protokolo-dosiero elŝutita de AWS
bazlinio - parametroj de la tempoperiodo uzata kiel bazo
kontrolpunkto - agordo de metrikoj por kontroli la staton de la datumbazo
kontrolpunkto_alert_historio - averta historio de datumbaza statokontrolaj metrikoj
pg_stat_db_queries — servotabelo de aktivaj petoj
agado_log — tabelo de servo de agado
kaptilo_oido - kaptilo-agorda servotabelo

Etapo 1 - kolektu rendimentostatistikojn kaj ricevu raportojn

Tabelo estas uzata por konservi statistikajn informojn. pg_stat_historio
pg_stat_history tabelstrukturo

                                          Tabelo "public.pg_stat_history" Kolumno | tajpu | Modifiloj--------------------+-------------------- --+---- -------------------------------- id | entjero | ne nula defaŭlta nextval('pg_stat_history_id_seq'::regclass) momentfoto_timestamp | tempomarko sen horzono | datumbazo_id | entjero | dbid | oid | uzulo | oid | queryid | bigint | konsulto | teksto | vokoj | bigint | tuta_tempo | duobla precizeco | min_tempo | duobla precizeco | maksimuma_tempo | duobla precizeco | meztempo | duobla precizeco | stddev_time | duobla precizeco | vicoj | bigint | shared_blks_hit | bigint | shared_blks_read | bigint | shared_blks_dirtied | bigint | shared_blks_written | bigint | loka_blks_hit | bigint | loka_blks_read | bigint | lokaj_blks_malpuraj | bigint | lokaj_blks_skribitaj | bigint | temp_blks_read | bigint | temp_blks_skribitaj | bigint | blk_legi_tempo | duobla precizeco | blk_skribi_tempo | duobla precizeco | bazlinio_id | entjero | Indeksoj: "pg_stat_history_pkey" PRIMA Ŝlosilo, btree (id) "database_idx" btree (database_id) "queryid_idx" btree (queryid) "snapshot_timestamp_idx" btree (snapshot_timestamp) Fremd-ŝlosila limo FOREIGN-datumbazo_FER_EJ_KID_ID_: datumbazo (id ) ON FORIGI KASKADO

Kiel vi povas vidi, la tabelo estas nur akumula viddatumo pg_stat_statements en la cela datumbazo.

La uzo de ĉi tiu tablo estas tre simpla.

pg_stat_historio reprezentos la akumulitajn statistikojn de demanda ekzekuto por ĉiu horo. Komence de ĉiu horo, post plenigo de la tabelo, statistikoj pg_stat_statements restarigi kun pg_stat_statements_reset ().
Notu: statistikoj estas kolektitaj por petoj kun daŭro de pli ol 1 sekundo.
Plenigante la tabelon 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;

Kiel rezulto, post certa tempodaŭro en la tabelo pg_stat_historio ni havos aron da momentfotoj de la enhavo de la tabelo pg_stat_statements cela datumbazo.

Fakte raportante

Uzante simplajn demandojn, vi povas ricevi sufiĉe utilajn kaj interesajn raportojn.

Agregaj datumoj por difinita tempodaŭro

Peto

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 ;

D.B. Tempo

to_char(intervalo '1 milisekundo' * pg_total_stat_history_rec.total_time, 'HH24:MI:SS.MS')

I/O Tempo

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

TOP10 SQL per totala_tempo

Peto

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 LAŬ TUTA EKZEKUTA TEMPO | #| queryid| vokoj| vokas %| tuta_tempo (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 per totala I/O-tempo

Peto

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 LAŬ TOTA I/O-TEMPO | #| queryid| vokoj| vokas %| I/O tempo (ms)|db I/O tempo % +----+-----------+-----------+------ -----+-------------------------------+----------- -- | 1| 4152624390| 2| .00001|00:08:31.616( 511616.592 ms.)| la 31.06-an de junio | 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 per maksimuma tempo de ekzekuto

Peto

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 PER MAKUSMA EKZEKUTA TEMPO | #| momentfoto| snapshotID| queryid| max_tempo (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 per SHARED bufro legi/skribi

Peto

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 PER KOMUNITA BUFFER LEGADO/SKRIBA | #| momentfoto| snapshotID| queryid| komunaj blokoj legi| komunaj blokoj skribu +----+------------------+-----------+---------- -+---------------------+--------------------- | 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 ------------------------------------------------- ------------------------------------------------

Histogramo de demanddistribuo per maksimuma ekzekuttempo

Petoj

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 HISTOGRAMO | TOTALVOKOJ : 33851920 | MIN TEMPO : 00:00:01.063 | MAX TEMPO : 00:02:01.869 --------------------------------- -------- ---------------------------- | min daŭro| maksimuma daŭro| vokoj +---------------------------------+-------------- ---------------------+---------- | 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 Momentfotoj per Demando por Sekundo

Petoj

--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 Momentfotoj ordigitaj de QueryPerSeconds-nombroj ------------------------------------- ------ ------------------------------------------- ------ ------------------------------------------- | #| momentfoto| snapshotID| vokoj| tuta dbtempo| QPS | I/O tempo | I/O tempo % +-----+------------------+-----------+------- ----+---------------------------------+---------- -+---------------------------------+----------- | 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:14( 00 ms.)| 4137| 2397326:00:04( 43.033 ms.)| .283033.854 | 665.924| 00/00/00.024 24.505:009 | 7| 04.04.2019| 15:00:4139( 2394416 ms.)| 00| 04:51.435:291435.010( 665.116 ms.)| .00 | 00| 12.025/12025.895/4.126 8:04.04.2019| 13| 00| 4135:2373043:00( 04 ms.)| 26.791| 266791.988:659.179:00( 00 ms.)| 00.064 | 64.261| 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:313.004( 00 ms.)| 00| 01.319:1319.676:1.666( XNUMX ms.)| XNUMX | XNUMX| XNUMX/XNUMX/XNUMX XNUMX:XNUMX| XNUMX| XNUMX| XNUMX:XNUMX:XNUMX( XNUMX ms.)| XNUMX| XNUMX:XNUMX:XNUMX( XNUMX ms.)| XNUMX

Hora Ekzekutado-Historio kun QueryPerSeconds kaj I/O Tempo

Peto

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

Teksto de ĉiuj SQL-elektoj

Peto

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

La rezulto

Kiel vi povas vidi, per sufiĉe simplaj rimedoj, vi povas akiri multajn utilajn informojn pri la laborkvanto kaj la stato de la datumbazo.

Notu:Se vi fiksas la keryid en la demandoj, tiam ni ricevos la historion por aparta peto (por ŝpari spacon, raportoj por aparta peto estas preterlasitaj).

Do, statistikaj datumoj pri demanda rendimento estas haveblaj kaj kolektitaj.
La unua etapo "kolekto de statistikaj datumoj" estas finita.

Vi povas daŭrigi al la dua etapo - "agordo de agado-metrikoj".
Efikecmonitorado de PostgreSQL-demandoj. Parto 1 - raportado

Sed tio estas tute alia historio.

Daŭrigota…

fonto: www.habr.com

Aldoni komenton