VACUM en ANALYSE zijn de twee belangrijkste onderhoudsbewerkingen voor PostgreSQL-databases.
Een vacuüm wordt gebruikt om ruimte terug te winnen die wordt ingenomen door "dode tupels" in een tafel. Een dode tuple wordt gemaakt wanneer een record wordt verwijderd of bijgewerkt (een verwijdering gevolgd door een invoeging). PostgreSQL verwijdert de oude rij niet fysiek uit de tabel, maar plaatst er een "markering" op zodat query's die rij niet retourneren. Wanneer een vacuümproces wordt uitgevoerd, wordt de ruimte die door deze dode tuples wordt ingenomen, gemarkeerd als herbruikbaar door andere tuples.
Een "analyse"-bewerking doet wat de naam zegt:het analyseert de inhoud van de tabellen van een database en verzamelt statistieken over de verdeling van waarden in elke kolom van elke tabel. De PostgreSQL-queryengine gebruikt deze statistieken om het beste queryplan te vinden. Als rijen worden ingevoegd, verwijderd en bijgewerkt in een database, veranderen ook de kolomstatistieken. ANALYSE – ofwel handmatig uitgevoerd door de DBA of automatisch door PostgreSQL na een autovacuüm – zorgt ervoor dat de statistieken up-to-date zijn.
Hoewel ze relatief eenvoudig klinken, zijn achter de schermen stofzuigen en analyseren twee complexe processen. Gelukkig hoeven DBA's zich niet veel zorgen te maken over hun internals. Ze zijn echter vaak verward over het handmatig uitvoeren van deze processen of het instellen van de optimale waarden voor de configuratieparameters.
In dit artikel zullen we enkele praktische tips voor VACUM en ANALYSE delen.
Tip 1:Voer geen handmatige VACUM of ANALYSE uit zonder reden
PostgreSQL-stofzuigen (autovacuüm of handmatig stofzuigen) minimaliseert het opzwellen van de tafel en voorkomt omhulling van transactie-ID's. Autovacuum herstelt niet de schijfruimte die wordt ingenomen door dode tupels. Echter, het uitvoeren van een VACUUM FULL commando zal dit doen. VACUUM FULL heeft echter zijn implicaties voor de prestaties. De doeltafel is uitsluitend vergrendeld tijdens de operatie, waardoor zelfs lezen op de tafel wordt voorkomen. Het proces maakt ook een volledige kopie van de tabel, wat extra schijfruimte vereist wanneer het wordt uitgevoerd. We raden aan om VACUUM FULL niet uit te voeren, tenzij er een zeer hoog percentage bloat is en query's zwaar te lijden hebben. We raden ook aan om hiervoor perioden met de laagste database-activiteit te gebruiken.
Het is ook een best practice om handmatige stofzuigers niet te vaak uit te voeren op de hele database; de doeldatabase kan al optimaal worden gestofzuigd door het autovacuümproces. Als gevolg hiervan verwijdert een handmatig vacuüm mogelijk geen dode tupels, maar veroorzaakt het onnodige I/O-belastingen of CPU-pieken. Indien nodig, moeten handmatige stofzuigers alleen per tafel worden uitgevoerd als dat nodig is, zoals lage verhoudingen van actieve rijen tot dode rijen, of grote openingen tussen autovacuüms. Handmatige stofzuigers moeten ook worden uitgevoerd wanneer de gebruikersactiviteit minimaal is.
Autovacuum houdt ook de gegevensdistributiestatistieken van een tabel up-to-date (het herbouwt ze niet). Bij handmatig uitvoeren, de ANALYSE commando herbouwt deze statistieken in plaats van ze bij te werken. Nogmaals, het opnieuw opbouwen van statistieken wanneer ze al optimaal zijn bijgewerkt door een regelmatig autovacuüm, kan onnodige druk op systeembronnen veroorzaken.
De tijd dat u ANALYZE handmatig moet uitvoeren, is onmiddellijk nadat de gegevens in bulk in de doeltabel zijn geladen. Een groot aantal (zelfs een paar honderd) nieuwe rijen in een bestaande tabel zal de verdeling van de kolomgegevens aanzienlijk scheeftrekken. De nieuwe rijen zorgen ervoor dat bestaande kolomstatistieken verouderd zijn. Wanneer de query-optimizer dergelijke statistieken gebruikt, kunnen de queryprestaties erg traag zijn. In deze gevallen is het een betere optie om de opdracht ANALYZE direct na het laden van gegevens uit te voeren om de statistieken volledig opnieuw op te bouwen dan te wachten tot het autovacuüm in werking treedt.
Tip 2:Autovacuümdrempel nauwkeurig afstellen
Het is essentieel om het autovacuum te controleren of af te stemmen en de configuratieparameters te analyseren in de postgresql.conf bestand of in individuele tabeleigenschappen om een balans te vinden tussen autovacuüm en prestatieverbetering.
PostgreSQL gebruikt twee configuratieparameters om te beslissen wanneer een autovacuüm moet worden gestart:
- autovacuum_vacuum_threshold :dit heeft een standaardwaarde van 50
- autovacuum_vacuum_scale_factor :dit heeft een standaardwaarde van 0.2
Samen vertellen deze parameters PostgreSQL om een autovacuüm te starten wanneer het aantal dode rijen in een tabel groter is dan het aantal rijen in die tabel vermenigvuldigd met de schaalfactor, plus de vacuümdrempel. Met andere woorden, PostgreSQL start autovacuüm op een tafel wanneer:
pg_stat_user_tables.n_dead_tup > (pg_class.reltuples x autovacuum_vacuum_scale_factor) + autovacuum_vacuum_threshold
Voor kleine tot middelgrote tafels kan dit voldoende zijn. Bijvoorbeeld, een tafel met 10.000 rijen, het aantal dode rijen moet meer dan 2.050 ((10.000 x 0,2) + 50) zijn voordat een autovacuüm begint.
Niet elke tabel in een database ervaart dezelfde snelheid van gegevenswijziging. Gewoonlijk zullen een paar grote tabellen frequente gegevenswijzigingen ondergaan, met als resultaat een groter aantal dode rijen. De standaardwaarden werken mogelijk niet voor dergelijke tabellen. Met de standaardwaarden moet een tabel met 1 miljoen rijen bijvoorbeeld meer dan 200.050 dode rijen hebben voordat een autovacuüm start ((1.000.000 x 0,2) + 50). Dit kan betekenen dat er langere tijd tussen autovacuüms zit, steeds langere autovacuümtijden en erger nog, autovacuüm werkt helemaal niet als actieve transacties op de tafel deze blokkeren.
Daarom moet het doel zijn om deze drempels op optimale waarden in te stellen, zodat autovacuüm met regelmatige tussenpozen kan plaatsvinden en niet lang duurt (en invloed heeft op gebruikerssessies), terwijl het aantal dode rijen relatief laag blijft.
Een benadering is om de ene of de andere parameter te gebruiken. Dus als we autovacuum_vacuum_scale_factor op 0 zetten en in plaats daarvan autovacuum_vacuum_threshold op bijvoorbeeld 5.000, wordt een tabel automatisch gevacuümeerd wanneer het aantal dode rijen meer dan 5.000 is.
Tip 3:Verfijn de automatische analyse van de drempel
Net als bij autovacuüm, gebruikt autoanalyse ook twee parameters die bepalen wanneer autovacuüm ook een autoanalyse activeert:
- autovacuum_analyze_threshold :dit heeft een standaardwaarde van 50
- autovacuum_analyze_scale_factor :dit heeft een standaardwaarde van 0,1
Net als autovacuum kan de parameter autovacuum_analyze_threshold worden ingesteld op een waarde die het aantal ingevoegde, verwijderde of bijgewerkte tupels in een tabel bepaalt voordat een automatische analyse begint. We raden aan om deze parameter apart in te stellen voor grote tabellen en tabellen met veel transacties. De tabelconfiguratie overschrijft de postgresql.conf-waarden.
Het onderstaande codefragment toont de SQL-syntaxis voor het wijzigen van de autovacuum_analyze_threshold-instelling voor een tabel.
ALTER TABLE <table_name> SET (autovacuum_analyze_threshold = <threshold rows>)
Tip 4:verfijn autovacuümwerkers
Een andere parameter die vaak over het hoofd wordt gezien door DBA's is autovacuum_max_workers , die een standaardwaarde van 3 heeft. Autovacuüm is geen enkel proces, maar een aantal afzonderlijke vacuümdraden die parallel lopen. De reden voor het specificeren van meerdere werknemers is om ervoor te zorgen dat het stofzuigen van grote tafels het stofzuigen van kleinere tafels en gebruikerssessies niet ophoudt. De parameter autovacuum_max_workers vertelt PostgreSQL om het aantal autovacuum worker-threads op te voeren om de opschoning uit te voeren.
Een gebruikelijke praktijk van PostgreSQL DBA's is om het aantal maximale werkthreads te verhogen in de hoop dat het autovacuüm zal versnellen. Dit werkt niet omdat alle threads dezelfde autovacuum_vacuum_cost_limit delen , die een standaardwaarde van 200 heeft. Aan elke autovacuümthread wordt een kostenlimiet toegewezen met behulp van de onderstaande formule:
individual thread’s cost_limit = autovacuum_vacuum_cost_limit / autovacuum_max_workers
De kosten van werk gedaan door een autovacuümdraad worden berekend met behulp van drie parameters:
- vacuum_cost_page_hit :dit heeft een standaardwaarde van 1
- vacuum_cost_page_miss :dit heeft een standaardwaarde van 10
- vacuum_cost_page_dirty :dit heeft een standaardwaarde van 20
Wat deze parameters betekenen is dit:
- Als een vacuümthread de gegevenspagina vindt die hij moet opschonen in de gedeelde buffer, bedragen de kosten 1.
- Als de gegevenspagina zich niet in de gedeelde buffer bevindt, maar in de OS-cache, zijn de kosten 10.
- Als de pagina als vuil moet worden gemarkeerd omdat de vacuümdraad dode rijen moest verwijderen, zijn de kosten 20.
Een groter aantal werkthreads verlaagt de kostenlimiet voor elke thread. Omdat aan elke thread een lagere kostenlimiet is toegewezen, zal deze vaker in slaapstand vallen omdat de kostendrempel gemakkelijk wordt bereikt, waardoor het hele vacuümproces uiteindelijk traag verloopt. We raden aan om de autovacuum_vacuum_cost_limit te verhogen naar een hogere waarde, bijvoorbeeld 2000, en vervolgens het maximum aantal werkthreads aan te passen.
Een betere manier is om deze parameters alleen af te stemmen op individuele tabellen als dat nodig is. Als het autovacuüm van een grote transactietafel bijvoorbeeld te lang duurt, kan de tafel tijdelijk worden geconfigureerd om zijn eigen vacuümkostenlimiet en kostenvertragingen te gebruiken. De kostenlimiet en vertraging overschrijven de systeembrede waarden die zijn ingesteld in postgresql.conf.
Het onderstaande codefragment laat zien hoe u afzonderlijke tabellen kunt configureren.
ALTER TABLE <table_name> SET (autovacuum_vacuum_cost_limit = <large_value>) ALTER TABLE <table_name> SET (autovacuum_vacuum_cost_delay = <lower_cost_delay>)
Als u de eerste parameter gebruikt, zorgt u ervoor dat de autovacuümthread die aan de tafel is toegewezen, meer werk zal doen voordat u gaat slapen. Het verlagen van de autovacuum_vacuum_cost_delay zal ook betekenen dat de thread minder tijd slaapt.
Laatste gedachten
Zoals u kunt zien, is het wijzigen van configuratieparameters voor vacuüm en analyse eenvoudig, maar het vereist eerst zorgvuldige observatie. Elke database is anders in termen van grootte, verkeerspatroon en transactiesnelheid. We raden DBA's aan om te beginnen met het verzamelen van voldoende informatie over hun database voordat ze de parameters wijzigen of een handmatig vacuüm-/analyseregime uitrollen. Dergelijke informatie kan zijn:
- Aantal rijen in elke tabel
- Aantal dode tuples in elke tabel
- De tijd van het laatste vacuüm voor elke tafel
- De tijd van de laatste analyse voor elke tafel
- De snelheid waarmee gegevens in elke tabel worden ingevoegd/bijgewerkt/verwijderd
- De tijd die autovacuüm in beslag neemt voor elke tafel
- Waarschuwingen over tafels die niet worden gestofzuigd
- Huidige prestaties van de meest kritieke zoekopdrachten en de tabellen waartoe ze toegang hebben
- Uitvoering van dezelfde zoekopdrachten na een handmatige vacuüm/analyse
Vanaf hier kunnen DBA's een paar "pilot"-tabellen selecteren om te beginnen met optimaliseren. Ze kunnen beginnen met het wijzigen van de vacuüm-/analyse-eigenschappen voor de tafels en de prestaties controleren. PostgreSQL is een slimme database-engine - DBA's zullen vaak merken dat het waarschijnlijk het beste is om PostgreSQL het stofzuigen en analyseren te laten doen in plaats van dat handmatig te doen.