sql >> Databasteknik >  >> RDS >> PostgreSQL

7 bästa praxis-tips för PostgreSQL-bulkdataladdning

Ibland behöver PostgreSQL-databaser importera stora mängder data i ett enda eller ett minimalt antal steg. Detta är allmänt känt som bulkdataimport där datakällan vanligtvis är en eller flera stora filer. Denna process kan ibland vara oacceptabelt långsam.

Det finns många anledningar till så dålig prestanda:index, triggers, främmande nycklar, GUID-primärnycklar eller till och med Write Ahead Log (WAL) kan alla orsaka förseningar.

I den här artikeln kommer vi att täcka några bästa praxis-tips för massimport av data till PostgreSQL-databaser. Det kan dock finnas situationer där inget av dessa tips kommer att vara en effektiv lösning. Vi rekommenderar läsare att överväga fördelarna och nackdelarna med alla metoder innan de tillämpas.

Tips 1:Ändra måltabell till ologgat läge

För PostgreSQL 9.5 och senare kan måltabellen först ändras till UNLOGGED, sedan ändras tillbaka till LOGGED när data har laddats:

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

UNLOGGED-läget säkerställer att PostgreSQL inte skickar tabellskrivoperationer till Write Ahead Log (WAL). Detta kan göra laddningsprocessen avsevärt snabb. Men eftersom operationerna inte loggas kan data inte återställas om det inträffar en krasch eller en oren serveravstängning under laddningen. PostgreSQL kommer automatiskt att trunkera alla ologgade tabeller när den startar om.

Ologgade tabeller replikeras inte heller till standby-servrar. I sådana fall måste befintliga replikationer tas bort före belastningen och återskapas efter belastningen. Beroende på mängden data i den primära noden och antalet väntelägen kan tiden för att återskapa replikering vara ganska lång och inte acceptabel av krav på hög tillgänglighet.

Vi rekommenderar följande bästa praxis för massinsättning av data i ologgade tabeller:

  • Göra en säkerhetskopia av tabellen och data innan du ändrar den till ett ologgat läge
  • Återskapa eventuell replikering till standby-servrar när dataladdningen är klar
  • Användning av ologgade massinlägg för tabeller som enkelt kan fyllas i igen (t.ex. stora uppslagstabeller eller dimensionstabeller)

Tips 2:Släpp och återskapa index

Befintliga index kan orsaka betydande förseningar under massdatainfogningar. Detta beror på att när varje rad läggs till måste motsvarande indexpost också uppdateras.

Vi rekommenderar att du släpper index i måltabellen där det är möjligt innan du startar massinsättningen och återskapar indexen när laddningen är klar. Återigen kan det vara tidskrävande att skapa index på stora tabeller, men det kommer i allmänhet att gå snabbare än att uppdatera indexen under laddning.

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

Det kan vara värt att tillfälligt öka maintenance_work_mem konfigurationsparameter precis innan du skapar indexen. Det ökade arbetsminnet kan hjälpa till att skapa indexen snabbare.

Ett annat alternativ för att spela säkert är att göra en kopia av måltabellen i samma databas med befintliga data och index. Den här nykopierade tabellen kan sedan testas med bulkinfogning för båda scenarierna:släpp-och-återskapa index eller dynamisk uppdatering av dem. Metoden som ger bättre prestanda kan sedan följas för livetabellen.

Tips 3:Släpp och återskapa främmande nycklar

Liksom index kan begränsningar för främmande nyckel också påverka bulkbelastningsprestanda. Detta beror på att varje främmande nyckel i varje infogat rad måste kontrolleras för att det finns en motsvarande primärnyckel. Bakom scenen använder PostgreSQL en trigger för att utföra kontrollen. När du laddar ett stort antal rader måste denna utlösare aktiveras för varje rad, vilket ökar omkostnaden.

Såvida det inte begränsas av affärsregler rekommenderar vi att du tar bort alla främmande nycklar från måltabellen, laddar data i en enda transaktion och sedan återskapar främmande nycklar efter att transaktionen har utförts.

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>)...

Återigen, öka maintenance_work_mem konfigurationsparameter kan förbättra prestandan för att återskapa främmande nyckelbegränsningar.

Tips 4:Inaktivera utlösare

INSERT- eller DELETE-utlösare (om laddningsprocessen också inbegriper radering av poster från måltabellen) kan orsaka förseningar vid laddning av massdata. Detta beror på att varje utlösare kommer att ha logik som måste kontrolleras och operationer som måste slutföras direkt efter att varje rad har infogats eller tagits bort.

Vi rekommenderar att du inaktiverar alla utlösare i måltabellen innan bulkladdning av data och aktiverar dem efter att laddningen är klar. Att inaktivera ALLA utlösare inkluderar också systemutlösare som upprätthåller kontroller av främmande nyckel.

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

Tips 5:Använd kommandot COPY

Vi rekommenderar att du använder PostgreSQL COPY kommando för att ladda data från en eller flera filer. COPY är optimerad för bulkdataladdningar. Det är mer effektivt än att köra ett stort antal INSERT-satser eller till och med INSERTS med flera värden.

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

Andra fördelar med att använda COPY inkluderar:

  • Den stöder både text- och binärfilimport
  • Det är transaktionellt till sin natur
  • Det låter dig specificera strukturen för indatafilerna
  • Den kan villkorligt ladda data med hjälp av en WHERE-sats

Tips 6:Använd INSERT med flera värden

Att köra flera tusen eller flera hundratusentals INSERT-satser kan vara ett dåligt val för bulkdatabelastning. Det beror på att varje enskilt INSERT-kommando måste analyseras och förberedas av frågeoptimeraren, gå igenom all kontroll av begränsningar, köras som en separat transaktion och loggas in i WAL. Användning av en enkel INSERT-sats med flera värden kan spara denna overhead.

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>),
...

INSERT-prestanda med flera värden påverkas av befintliga index. Vi rekommenderar att du tar bort indexen innan du kör kommandot och återskapar indexen efteråt.

Ett annat område att vara medveten om är mängden minne som är tillgängligt för PostgreSQL för att köra INSERTs med flera värden. När en INSERT med flera värden körs måste ett stort antal ingångsvärden passa i RAM-minnet, och om det inte finns tillräckligt med minne kan processen misslyckas.

Vi rekommenderar att du ställer in effective_cache_size parameter till 50 % och shared_buffer parameter till 25 % av maskinens totala RAM-minne. För säkerhets skull kör den också en serie INSERT med flera värden där varje sats har värden för 1000 rader.

Tips 7:Kör ANALYS

Detta är inte relaterat till att förbättra prestanda för massdataimport, men vi rekommenderar starkt att du kör ANALYS kommandot i måltabellen direkt efter massimporten. Ett stort antal nya rader kommer att avsevärt skeva datafördelningen i kolumner och kommer att göra att all befintlig statistik i tabellen blir inaktuell. När frågeoptimeraren använder inaktuell statistik kan frågeprestanda vara oacceptabelt dålig. Genom att köra kommandot ANALYSE kommer all befintlig statistik att uppdateras.

Sluta tankar

Bulkdataimport kanske inte sker varje dag för en databasapplikation, men det finns en prestandapåverkan på frågor när den körs. Det är därför det är nödvändigt att minimera laddningstiden så bra som möjligt. En sak DBA:er kan göra för att minimera överraskning är att testa belastningsoptimeringarna i en utvecklings- eller iscensättningsmiljö med liknande serverspecifikationer och PostgreSQL-konfigurationer. Varje dataladdningsscenario är olika, och det är bäst att prova varje metod och hitta den som fungerar.


  1. psycopg2 hur hantera TypeError:inte alla argument konverteras under strängformatering

  2. SQL Server sp_msforeachtable användning för att välja endast de tabeller som uppfyller något villkor

  3. Konvertera SQL2008 RDL-fil till SQL2005

  4. MySQL> Tabell finns inte. Men det gör det (eller det borde det)