Se fylla i en databas i PostgreSQL-manualen, depesz's excellent-as-usual-artikel om ämnet och denna SO-fråga.
(Observera att det här svaret handlar om att massinläsa data till en befintlig DB eller att skapa en ny. Om du är intresserad återställ DB prestanda med pg_restore
eller psql
körning av pg_dump
output, mycket av detta gäller inte eftersom pg_dump
och pg_restore
redan gör saker som att skapa triggers och index efter att en schema+dataåterställning är klar) .
Det finns mycket att göra. Den idealiska lösningen skulle vara att importera till en UNLOGGED
tabell utan index, ändra den sedan till loggad och lägg till indexen. Tyvärr i PostgreSQL 9.4 finns det inget stöd för att ändra tabeller från UNLOGGED
till inloggad. 9.5 lägger till ALTER TABLE ... SET LOGGED
för att tillåta dig att göra detta.
Om du kan ta din databas offline för massimporten, använd pg_bulkload
.
Annars:
-
Inaktivera alla utlösare på bordet
-
Släpp index innan du startar importen, återskapa dem efteråt. (Det krävs mycket mindre tid för att bygga ett index i ett steg än att lägga till samma data successivt, och det resulterande indexet är mycket mer kompakt).
-
Om du gör importen inom en enskild transaktion är det säkert att släppa begränsningar för främmande nyckel, göra importen och återskapa begränsningarna innan du genomför. Gör inte detta om importen är uppdelad på flera transaktioner eftersom du kan införa ogiltiga data.
-
Om möjligt, använd
COPY
istället förINSERT
s -
Om du inte kan använda
COPY
överväg att användaINSERT
med flera värden om det är praktiskt. Du verkar redan göra det här. Försök inte att lista för många värden i en endaVALUES
fastän; dessa värden måste passa in i minnet ett par gånger om, så håll det till några hundra per påstående. -
Kombinera dina bilagor till explicita transaktioner, gör hundratusentals eller miljontals bilagor per transaktion. Det finns ingen praktisk gräns AFAIK, men batchning låter dig återhämta dig från ett fel genom att markera början av varje batch i dina indata. Återigen, du verkar redan göra det här.
-
Använd
synchronous_commit=off
och en enormcommit_delay
för att minska fsync()-kostnaderna. Detta hjälper dock inte mycket om du har samlat ditt arbete i stora transaktioner. -
INSERT
ellerKOPIERA
parallellt från flera förbindelser. Hur många beror på hårdvarans diskundersystem; som en tumregel vill du ha en anslutning per fysisk hårddisk om du använder direktansluten lagring. -
Ställ in en hög
max_wal_size
värde (checkpoint_segments
i äldre versioner) och aktiveralog_checkpoints
. Titta på PostgreSQL-loggarna och se till att den inte klagar över kontrollpunkter som förekommer för ofta. -
Om och bara om du inte har något emot att förlora hela ditt PostgreSQL-kluster (din databas och alla andra i samma kluster) till katastrofal korruption om systemet kraschar under importen, kan du stoppa Pg, ställ in
fsync=off , starta Pg, gör din import, stoppa sedan Pg och ställ in
fsync=on
på nytt. Se WAL-konfiguration. Gör inte detta om det redan finns någon data som du bryr dig om i någon databas på din PostgreSQL-installation. Om du ställer infsync=av
du kan också ställa infull_page_writes=off
; igen, kom bara ihåg att slå på den igen efter din import för att förhindra databaskorruption och dataförlust. Se icke-hållbara inställningar i sidmanualen.
Du bör också titta på hur du ställer in ditt system:
-
Använd god kvalitet SSD:er för lagring så mycket som möjligt. Bra SSD:er med pålitliga, strömskyddade återskrivningscacher gör commit-hastigheterna otroligt snabbare. De är mindre fördelaktiga när du följer råden ovan - vilket minskar diskrensningar / antal
fsync()
s - men kan fortfarande vara till stor hjälp. Använd inte billiga SSD-enheter utan ordentligt strömavbrottsskydd om du inte bryr dig om att behålla dina data. -
Om du använder RAID 5 eller RAID 6 för direktansluten lagring, sluta nu. Säkerhetskopiera dina data, strukturera om din RAID-array till RAID 10 och försök igen. RAID 5/6 är hopplösa för bulkskrivprestanda - även om en bra RAID-kontroller med en stor cache kan hjälpa.
-
Om du har möjlighet att använda en hårdvaru-RAID-kontroller med en stor batteristödd återskrivningscache kan detta verkligen förbättra skrivprestandan för arbetsbelastningar med många commits. Det hjälper inte lika mycket om du använder async commit med en commit_delay eller om du gör färre stora transaktioner under massladdning.
-
Om möjligt, lagra WAL (
pg_wal
, ellerpg_xlog
i gamla versioner) på en separat disk/diskarray. Det finns ingen mening med att använda ett separat filsystem på samma disk. Människor väljer ofta att använda ett RAID1-par för WAL. Återigen, detta har mer effekt på system med höga commit-hastigheter, och det har liten effekt om du använder en ologgad tabell som dataladdningsmål.
Du kanske också är intresserad av Optimera PostgreSQL för snabbtestning.