sql >> Database >  >> RDS >> PostgreSQL

7 praktische tips voor het in bulk laden van postgreSQL-gegevens

Soms moeten PostgreSQL-databases grote hoeveelheden gegevens in één of een minimaal aantal stappen importeren. Dit staat algemeen bekend als bulkgegevensimport, waarbij de gegevensbron doorgaans een of meer grote bestanden is. Dit proces kan soms onaanvaardbaar traag zijn.

Er zijn veel redenen voor zulke slechte prestaties:indexen, triggers, externe sleutels, GUID-primaire sleutels of zelfs het Write Ahead Log (WAL) kunnen allemaal vertragingen veroorzaken.

In dit artikel behandelen we enkele praktische tips voor het bulksgewijs importeren van gegevens in PostgreSQL-databases. Er kunnen zich echter situaties voordoen waarin geen van deze tips een efficiënte oplossing is. We raden lezers aan om de voor- en nadelen van elke methode te overwegen voordat ze deze toepassen.

Tip 1:verander doeltabel in niet-gelogde modus

Voor PostgreSQL 9.5 en hoger kan de doeltabel eerst worden gewijzigd in UNLOGGED en vervolgens weer worden gewijzigd in LOGGED zodra de gegevens zijn geladen:

ALTER TABLE <target table> SET UNLOGGED
<bulk data insert operations…>
ALTER TABLE <target table> LOGGED

De UNLOGGED-modus zorgt ervoor dat PostgreSQL geen schrijfbewerkingen voor tabellen naar het Write Ahead Log (WAL) verzendt. Dit kan het laadproces aanzienlijk snel maken. Omdat de bewerkingen echter niet worden vastgelegd, kunnen gegevens niet worden hersteld als er een crash is of een onreine server wordt afgesloten tijdens het laden. PostgreSQL zal automatisch elke niet-gelogde tabel afkappen zodra deze opnieuw is opgestart.

Ook worden niet-geregistreerde tabellen niet gerepliceerd naar standby-servers. In dergelijke gevallen moeten bestaande replicaties vóór het laden worden verwijderd en na het laden opnieuw worden gemaakt. Afhankelijk van de hoeveelheid gegevens in het primaire knooppunt en het aantal standbys, kan de tijd voor het opnieuw maken van replicatie behoorlijk lang zijn en niet acceptabel vanwege hoge beschikbaarheidsvereisten.

We raden de volgende best practices aan voor het bulksgewijs invoegen van gegevens in niet-gelogde tabellen:

  • Een back-up maken van de tabel en gegevens voordat u deze wijzigt in een niet-gelogde modus
  • Replicatie naar standby-servers opnieuw maken zodra het laden van gegevens is voltooid
  • Niet-gelogde bulkinvoegingen gebruiken voor tabellen die gemakkelijk opnieuw kunnen worden ingevuld (bijv. grote opzoektabellen of dimensietabellen)

Tip 2:Indexen verwijderen en opnieuw maken

Bestaande indexen kunnen aanzienlijke vertragingen veroorzaken bij het invoegen van bulkgegevens. Dit komt omdat wanneer elke rij wordt toegevoegd, het bijbehorende indexitem ook moet worden bijgewerkt.

We raden aan waar mogelijk indexen in de doeltabel te plaatsen voordat u de bulkinvoeging start, en de indexen opnieuw te maken zodra het laden is voltooid. Nogmaals, het maken van indexen op grote tabellen kan tijdrovend zijn, maar het zal over het algemeen sneller zijn dan het bijwerken van de indexen tijdens het laden.

DROP INDEX <index_name1>, <index_name2> … <index_name_n>
<bulk data insert operations…>
CREATE INDEX <index_name> ON <target_table>(column1, …,column n)

Het kan de moeite waard zijn om de maintenance_work_mem . tijdelijk te verhogen configuratieparameter net voordat de indexen worden gemaakt. Het verhoogde werkgeheugen kan helpen om de indexen sneller te maken.

Een andere optie om op veilig te spelen is om een ​​kopie te maken van de doeltabel in dezelfde database met bestaande gegevens en indexen. Deze nieuw gekopieerde tabel kan vervolgens worden getest met bulkinsertie voor beide scenario's:drop-and-recreate indexen of dynamisch bijwerken ervan. De methode die betere prestaties oplevert kan dan gevolgd worden voor de live tafel.

Tip 3:laat externe sleutels vallen en maak ze opnieuw

Net als indexen kunnen beperkingen van externe sleutels ook van invloed zijn op de prestaties van bulkladingen. Dit komt omdat elke externe sleutel in elke ingevoegde rij moet worden gecontroleerd op het bestaan ​​van een bijbehorende primaire sleutel. Achter de schermen gebruikt PostgreSQL een trigger om de controle uit te voeren. Bij het laden van een groot aantal rijen moet deze trigger voor elke rij worden geactiveerd, wat bijdraagt ​​aan de overhead.

Tenzij beperkt door bedrijfsregels, raden we aan alle externe sleutels uit de doeltabel te verwijderen, de gegevens in een enkele transactie te laden en vervolgens de externe sleutels opnieuw te maken nadat de transactie is uitgevoerd.

ALTER TABLE <target_table> 
DROP CONSTRAINT <foreign_key_constraint>

BEGIN TRANSACTION
<bulk data insert operations…>
COMMIT

ALTER TABLE <target_table> 
ADD CONSTRAINT <foreign key constraint>  
FOREIGN KEY (<foreign_key_field>) 
REFERENCES <parent_table>(<primary key field>)...

Nogmaals, het verhogen van de maintenance_work_mem configuratieparameter kan de prestaties verbeteren van het opnieuw creëren van externe sleutelbeperkingen.

Tip 4:Schakel triggers uit

INSERT- of DELETE-triggers (als het laadproces ook het verwijderen van records uit de doeltabel omvat) kunnen vertragingen veroorzaken bij het laden van bulkgegevens. Dit komt omdat elke trigger logica heeft die moet worden gecontroleerd en bewerkingen die moeten worden voltooid direct nadat elke rij is INSERTed of DELETED.

We raden aan om alle triggers in de doeltabel uit te schakelen voordat gegevens in bulk worden geladen en ze weer in te schakelen nadat het laden is voltooid. Het uitschakelen van ALLE triggers omvat ook systeemtriggers die controles op externe sleutelbeperkingen afdwingen.

ALTER TABLE <target table> DISABLE TRIGGER ALL
<bulk data insert operations…>
ALTER TABLE <target table> ENABLE TRIGGER ALL

Tip 5:Gebruik het COPY-commando

We raden aan om de PostgreSQL COPY . te gebruiken commando om gegevens uit een of meer bestanden te laden. COPY is geoptimaliseerd voor het laden van bulkgegevens. Het is efficiënter dan het uitvoeren van een groot aantal INSERT-instructies of zelfs INSERTS met meerdere waarden.

COPY <target table> [( column1>, … , <column_n>)]
FROM  '<file_name_and_path>' 
WITH  (<option1>, <option2>, … , <option_n>)

Andere voordelen van het gebruik van COPY zijn onder meer:

  • Het ondersteunt zowel het importeren van tekst als binaire bestanden
  • Het is een transactie van aard
  • Hiermee kunt u de structuur van de invoerbestanden specificeren
  • Het kan voorwaardelijk gegevens laden met behulp van een WHERE-clausule

Tip 6:Gebruik INSERT met meerdere waarden

Het uitvoeren van enkele duizenden of enkele honderdduizenden INSERT-instructies kan een slechte keuze zijn voor het bulksgewijs laden van gegevens. Dat komt omdat elke afzonderlijke INSERT-opdracht moet worden geparseerd en voorbereid door de query-optimizer, alle beperkingscontrole moet doorlopen, als een afzonderlijke transactie moet worden uitgevoerd en moet worden aangemeld bij de WAL. Het gebruik van een enkelvoudig INSERT-statement met meerdere waarden kan deze overhead besparen.

INSERT INTO <target_table> (<column1>, <column2>, …, <column_n>) 
VALUES 
(<value a>, <value b>, …, <value x>),
(<value 1>, <value 2>, …, <value n>),
(<value A>, <value B>, …, <value Z>),
(<value i>, <value ii>, …, <value L>),
...

De prestaties van INSERT met meerdere waarden worden beïnvloed door bestaande indexen. We raden u aan de indexen te verwijderen voordat u de opdracht uitvoert en de indexen daarna opnieuw te maken.

Een ander gebied waar u op moet letten, is de hoeveelheid geheugen die beschikbaar is voor PostgreSQL voor het uitvoeren van INSERT's met meerdere waarden. Wanneer een INSERT met meerdere waarden wordt uitgevoerd, moet een groot aantal invoerwaarden in het RAM passen, en tenzij er voldoende geheugen beschikbaar is, kan het proces mislukken.

We raden aan om de effectieve_cache_size . in te stellen parameter op 50%, en shared_buffer parameter tot 25% van het totale RAM-geheugen van de machine. Voor de zekerheid voert het ook een reeks INSERT's met meerdere waarden uit, waarbij elke instructie waarden heeft voor 1000 rijen.

Tip 7:Voer ANALYSE uit

Dit heeft niets te maken met het verbeteren van de prestaties van bulkgegevensimport, maar we raden u ten zeerste aan de ANALYZE . uit te voeren commando op de doeltabel onmiddellijk na de bulkimport. Een groot aantal nieuwe rijen zal de gegevensverdeling in kolommen aanzienlijk scheeftrekken en ervoor zorgen dat bestaande statistieken in de tabel verouderd zijn. Wanneer de query-optimizer verouderde statistieken gebruikt, kunnen de queryprestaties onaanvaardbaar slecht zijn. Het uitvoeren van de opdracht ANALYZE zorgt ervoor dat alle bestaande statistieken worden bijgewerkt.

Laatste gedachten

Het importeren van bulkgegevens gebeurt misschien niet elke dag voor een databasetoepassing, maar er is een prestatie-impact op query's wanneer deze wordt uitgevoerd. Daarom is het noodzakelijk om de laadtijd zo goed mogelijk te minimaliseren. Een ding dat DBA's kunnen doen om elke verrassing tot een minimum te beperken, is door de belastingoptimalisaties te testen in een ontwikkel- of staging-omgeving met vergelijkbare serverspecificaties en PostgreSQL-configuraties. Elk scenario voor het laden van gegevens is anders en het is het beste om elke methode uit te proberen en de methode te vinden die werkt.


  1. JSON in SQL Server

  2. Vraag over SQL unieke varchar hoofdlettergevoeligheid

  3. Hoe de grootte van een gegevensbestand in SQL Server (T-SQL) te verkleinen

  4. Gegevensbestanden verplaatsen in SQL Server - Deel 1