sql >> Databasteknik >  >> RDS >> PostgreSQL

Mina favoritpostgreSQL-tillägg - del två

Detta är den andra delen av min blogg "My Favorite PostgreSQL Extensions" där jag hade introducerat dig för två PostgreSQL-tillägg, postgres_fdw och pg_partman. I den här delen kommer jag att utforska ytterligare tre.

pgAudit

Nästa PostgreSQL-utvidgning av intresse är i syfte att uppfylla revisionskrav från olika statliga, finansiella och andra certifieringsorgan som ISO, BSI och FISCAM, etc. Standardloggningsmöjligheten som PostgreSQL erbjuder inbyggt med log_statement =allt är användbart för övervakning, men det ger inte de detaljer som krävs för att följa eller möta revisionen. Tillägget pgAudit fokuserar på detaljerna om vad som hände under huven, medan en databas tillfredsställde en begäran om applikation.

En revisionsspår eller revisionslogg skapas och uppdateras av en standardloggningsfunktion som tillhandahålls av PostgreSQL, som tillhandahåller detaljerad sessions- och/eller objektgranskningsloggning. Revisionsspåret som skapats av pgAudit kan bli enormt i storlek beroende på revisionsinställningarna, så man måste vara noga med att bestämma vad och hur mycket revision som krävs i förväg. En kort demo i följande avsnitt visar hur pgAudit konfigureras och används.

Loggspåret skapas i PostgreSQL-databasklusterloggen som finns på PGDATA/loggplatsen men granskningsloggmeddelandena har prefixet "AUDIT:" för att skilja mellan vanliga databasbakgrundsmeddelanden och granskningslogg uppgifter.

Demo

Den officiella dokumentationen för pgAudit förklarar att det finns en separat version av pgAudit för varje större version av PostgreSQL för att stödja ny funktionalitet som introduceras i varje PostgreSQL-utgåva. Versionen av PostgreSQL i denna demo är 11, så versionen av pgAudit kommer att vara från grenen 1.3.X. Pgaudit.log är den grundläggande parametern som ska ställas in som styr vilka klasser av uttalanden som kommer att loggas. Den kan ställas in med en SET för en sessionsnivå eller i postgresql.conf-filen för att tillämpas globalt.

postgres=# set pgaudit.log = 'read, write, role, ddl, misc';

SET



cat $PGDATA/pgaudit.log

pgaudit.log = 'read, write, role, ddl, misc'



db_replica=# show pgaudit.log;

         pgaudit.log

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

 read, write, role, ddl, misc

(1 row)



2020-01-29 22:51:49.289 AEDT 4710 db_replica postgres [local] psql LOG:  AUDIT: SESSION,3,1,MISC,SHOW,,,show pgaudit.log;,<not logged>



db_replica=# create table t1 (f1 integer, f2 varchar);

CREATE TABLE



2020-01-29 22:52:08.327 AEDT 4710 db_replica postgres [local] psql LOG:  AUDIT: SESSION,4,1,DDL,CREATE TABLE,,,"create table t1 (f1 integer, f2 varchar);",<not logged>



db_replica=#  insert into t1 values (1,'one');

INSERT 0 1

db_replica=#  insert into t1 values (2,'two');

INSERT 0 1

db_replica=#  insert into t1 values (3,'three');

INSERT 0 1

2020-01-29 22:52:19.261 AEDT 4710 db_replica postgres [local] psql LOG:  AUDIT: SESSION,5,1,WRITE,INSERT,,,"insert into t1 values (1,'one');",<not logged>

20-01-29 22:52:38.145 AEDT 4710 db_replica postgres [local] psql LOG:  AUDIT: SESSION,6,1,WRITE,INSERT,,,"insert into t1 values (2,'two');",<not logged>

2020-01-29 22:52:44.988 AEDT 4710 db_replica postgres [local] psql LOG:  AUDIT: SESSION,7,1,WRITE,INSERT,,,"insert into t1 values (3,'three');",<not logged>



db_replica=# select * from t1 where f1 >= 2;

 f1 |  f2

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

  2 | two

  3 | three

(2 rows)



2020-01-29 22:53:09.161 AEDT 4710 db_replica postgres [local] psql LOG:  AUDIT: SESSION,9,1,READ,SELECT,,,select * from t1 where f1 >= 2;,<not logged>



db_replica=# grant select on t1 to usr_replica;

GRANT



2020-01-29 22:54:25.283 AEDT 4710 db_replica postgres [local] psql LOG:  AUDIT: SESSION,13,1,ROLE,GRANT,,,grant select on t1 to usr_replica;,<not logged>



db_replica=# alter table t1 add f3 date;

ALTER TABLE



2020-01-29 22:55:17.440 AEDT 4710 db_replica postgres [local] psql LOG:  AUDIT: SESSION,23,1,DDL,ALTER TABLE,,,alter table t1 add f3 date;,<not logged>



db_replica=# checkpoint;

CHECKPOINT



2020-01-29 22:55:50.349 AEDT 4710 db_replica postgres [local] psql LOG:  AUDIT: SESSION,33,1,MISC,CHECKPOINT,,,checkpoint;,<not logged>



db_replica=# vacuum t1;

VACUUM



2020-01-29 22:56:03.007 AEDT 4710 db_replica postgres [local] psql LOG:  AUDIT: SESSION,34,1,MISC,VACUUM,,,vacuum t1;,<not logged>



db_replica=# show log_statement;

 log_statement

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

 none



2020-01-29 22:56:14.740 AEDT 4710 db_replica postgres [local] psql LOG:  AUDIT: SESSION,36,1,MISC,SHOW,,,show log_statement;,<not logged>

Loggposterna, som visas i demon ovan, skrivs endast till serverns bakgrundsloggfil när parametern log_statement är inställd, men i detta fall är den inte konfigurerad utan revisionsmeddelandena skrivs i kraft av av pgaudit.log-parametern som framgår av demon. Det finns mer kraftfulla alternativ tillgängliga för att uppfylla alla dina databasrevisionskrav inom PostgreSQL, som kan konfigureras genom att följa den officiella dokumentationen för pgaudit här eller på github repository.pg_repack

Detta är ett favorittillägg bland många PostgreSQL-ingenjörer som är direkt involverade i att hantera och behålla den allmänna hälsan hos ett PostgreSQL-kluster. Anledningen till det kommer att diskuteras lite senare, men det här tillägget erbjuder funktionen att ta bort databasuppsvällning i en PostgreSQL-databas, vilket är ett av de tjatande problemen bland mycket stora PostgreSQL-databaskluster som kräver omorganisering av databasen.

Eftersom en PostgreSQL-databas genomgår konstanta och tunga SKRIVNINGAR (uppdateringar och raderingar), markeras den gamla datan som raderad medan den nya versionen av raden infogas, men den gamla data raderas faktiskt inte från en datablock. Detta kräver en periodisk underhållsoperation som kallas dammsugning, vilket är en automatisk procedur som körs i bakgrunden och rensar alla "markerade som raderade" rader. Denna process kallas ibland för sophämtning i vardagliga termer.

Dammsugningsprocessen ger vanligtvis plats för databasoperationerna under mer hektiska tider. Det minst restriktiva sättet att dammsuga till förmån för databasoperationer resulterar i ett stort antal "markerade som borttagna" rader som får databaser att växa ur proportion som kallas "databasuppsvällning". Det finns en kraftfull dammsugningsprocess som kallas VACUUM FULL, men som resulterar i att man får ett exklusivt lås på databasobjektet som bearbetas, vilket stoppar databasoperationer på det objektet.

pg_repack

Det är av denna anledning som pg_repack är en hit bland PostgreSQL DBA:er och ingenjörer, eftersom det gör jobbet med en normal dammsugningsprocess men erbjuder en effektivitet av VACUUM FULL genom att inte skaffa ett exklusivt lås på en databas objekt, kort sagt, det fungerar online. Den officiella dokumentationen här förklarar mer om de andra metoderna för att omorganisera en databas men en snabb demo enligt nedan kommer att sätta saker i lämpligt ljus för bättre förståelse. Det finns ett krav att måltabellen måste ha minst en kolumn definierad som en PRIMÄRNYCKEL, vilket är en allmän norm i de flesta av produktionsdatabasens inställningar.

Demo

Den grundläggande demon visar installationen och användningen av pg_repack i en testmiljö. Den här demon använder version 1.4.5 av pg_repack som är den senaste versionen av detta tillägg vid tidpunkten för publicering av denna blogg. En demotabell t1 har initialt 80 000 rader som genomgår en massiv operation med borttagning, som raderar var 5:e rad i tabellen. En körning av pg_repack visar storleken på tabellen före och efter.

mydb=# CREATE EXTENSION pg_repack;

CREATE EXTENSION



mydb=# create table t1 (no integer primary key, f_name VARCHAR(20), l_name VARCHAR(20), d_o_b date);

CREATE TABLE

mydb=# insert into t1 (select generate_series(1,1000000,1),'a'||

mydb(# generate_series(1,1000000,1),'a'||generate_series(1000000,1,-1),

mydb(# cast( now() - '1 year'::interval * random()  as date ));

INSERT 0 1000000



mydb=# SELECT pg_size_pretty( pg_total_relation_size('t1'));

 pg_size_pretty

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

 71 MB

(1 row)



mydb=# CREATE or replace FUNCTION delete5() RETURNS void AS $$

mydb$# declare

mydb$# counter integer := 0;

mydb$# BEGIN

mydb$#

mydb$#  while counter <= 1000000

mydb$# loop

mydb$# delete from t1 where no=counter;

mydb$# counter := counter + 5;

mydb$# END LOOP;

mydb$# END;

mydb$# $$ LANGUAGE plpgsql;

CREATE FUNCTION

Delete5-funktionen tar bort 200000 rader från t1-tabellen med en räknare som ökar 5 räkningar

mydb=# select delete5();

 delete5

------



(1 row)

mydb=# SELECT pg_size_pretty( pg_total_relation_size('t1'));

 pg_size_pretty

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

 71 MB

(1 row)



$ pg_repack -t t1 -N -n -d mydb -p 5433

INFO: Dry run enabled, not executing repack

INFO: repacking table "public.t1"



$ pg_repack -t t1 -n -d mydb -p 5433

INFO: repacking table "public.t1"



mydb=# SELECT pg_size_pretty( pg_total_relation_size('t1'));

 pg_size_pretty

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

 57 MB

(1 row)

Som visas ovan ändras inte tabellens ursprungliga storlek efter att ha kört delete5-funktionen, vilket visar att raderna fortfarande finns i tabellen. Utförandet av pg_repack rensar de "markerade som borttagna" rader från t1-tabellen och minskar storleken på t1-tabellen till 57 MB. En annan bra sak med pg_repack är ett alternativ för torrkörning med -N-flagga, med hjälp av vilken du kan kontrollera vad som kommer att köras under en faktisk körning.

HypoPG

Nästa intressanta tillägg är identisk med ett populärt koncept som kallas osynliga index bland proprietära databasservrar. HypoPG-tillägget gör det möjligt för en DBA att se effekten av att introducera ett hypotetiskt index (som inte finns) och om det kommer att förbättra prestandan för en eller flera frågor, och därav namnet HypoPG.

Skapandet av ett hypotetiskt index kräver inga CPU- eller diskresurser, men det förbrukar en anslutnings privata minne. Eftersom det hypotetiska indexet inte lagras i några databaskatalogtabeller, så finns det ingen effekt av tabelluppsvällning. Det är av denna anledning som ett hypotetiskt index inte kan användas i en EXPLAIN ANALYZE-sats medan en vanlig EXPLAIN är ett bra sätt att bedöma om ett potentiellt index kommer att användas av en given problematisk fråga. Här är en snabb demo för att förklara hur HypoPG fungerar.

Demo

Jag ska skapa en tabell som innehåller 100 000 rader med generera_serier och köra ett par enkla frågor för att visa skillnaden i kostnadsuppskattningar med och utan hypotetiska index.

olap=# CREATE EXTENSION hypopg;

CREATE EXTENSION



olap=# CREATE TABLE stock (id integer, line text);

CREATE TABLE



olap=# INSERT INTO stock SELECT i, 'line ' || i FROM generate_series(1, 100000) i;

INSERT 0 100000



olap=# ANALYZE STOCK;

ANALYZE



olap=#  EXPLAIN SELECT line FROM stock WHERE id = 1;

                       QUERY PLAN

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

 Seq Scan on stock  (cost=0.00..1791.00 rows=1 width=10)

   Filter: (id = 1)

(2 rows)

olap=# SELECT * FROM hypopg_create_index('CREATE INDEX ON stock (id)') ;

 indexrelid |       indexname

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

      25398 | <25398>btree_stock_id

(1 row)



olap=# EXPLAIN SELECT line FROM stock WHERE id = 1;

                                     QUERY PLAN

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

 Index Scan using <25398>btree_stock_id on stock  (cost=0.04..8.06 rows=1 width=10)

   Index Cond: (id = 1)

(2 rows)



olap=# EXPLAIN ANALYZE SELECT line FROM stock WHERE id = 1;

                                             QUERY PLAN

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

 Seq Scan on stock  (cost=0.00..1791.00 rows=1 width=10) (actual time=0.028..41.877 rows=1 loops=1)

   Filter: (id = 1)

   Rows Removed by Filter: 99999

 Planning time: 0.057 ms

 Execution time: 41.902 ms

(5 rows)



olap=# SELECT indexname, pg_size_pretty(hypopg_relation_size(indexrelid))

olap-#   FROM hypopg_list_indexes() ;

       indexname       | pg_size_pretty

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

 <25398>btree_stock_id | 2544 kB

(1 row)



olap=# SELECT pg_size_pretty(pg_relation_size('stock'));

 pg_size_pretty

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

 4328 kB

(1 row)

Ovanstående utställning visar hur den uppskattade totala kostnaden kan minskas från 1791 till 8,06 genom att lägga till ett index i fältet "id" i tabellen för att optimera en enkel fråga. Det bevisar också att indexet inte riktigt används när frågan exekveras med en EXPLAIN ANALYZE som exekverar frågan i realtid. Det finns också ett sätt att ta reda på ungefär hur mycket diskutrymme indexet upptar med hjälp av funktionen hypopg_list_indexes i tillägget.

HypoPG har några andra funktioner för att hantera hypotetiska index och utöver det erbjuder den också ett sätt att ta reda på om partitionering av en tabell kommer att förbättra prestandan för frågor som hämtar en stor datamängd. Det finns ett hypotetiskt partitioneringsalternativ för HypoPG-tillägget och mer av det kan följas genom att hänvisa till den officiella dokumentationen.

Slutsats

Som nämnts i del ett har PostgreSQL utvecklats under åren och bara blivit större, bättre och snabbare med snabb utveckling både i den inbyggda källkoden såväl som plug and play-tillägg. En öppen källkodsversion av nya PostgreSQL kan vara mest lämpad för många IT-butiker som kör en av de stora proprietära databasservrarna, för att minska deras IT CAPEX och OPEX.

Det finns gott om PostgreSQL-tillägg som erbjuder funktioner som sträcker sig från övervakning till hög tillgänglighet och från skalning till dumpning av binära datafiler till läsbart format. Förhoppningen är att demonstrationerna ovan har kastat enormt ljus över den maximala potentialen och kraften hos en PostgreSQL-databas.


  1. Rekursion på databasfråga för att få hierarkiska resultat med Hibernate - Java

  2. Postgresql enum vad är fördelarna och nackdelarna?

  3. PostgreSQL materialiserad vy

  4. Hur vet man att installerad Oracle Client är 32-bitars eller 64-bitars?