sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur man påskyndar insättningsprestanda i PostgreSQL

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ör INSERT s

  • Om du inte kan använda COPY överväg att använda INSERT 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 enda VALUES 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 enorm commit_delay för att minska fsync()-kostnaderna. Detta hjälper dock inte mycket om du har samlat ditt arbete i stora transaktioner.

  • INSERT eller KOPIERA 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 aktivera log_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 in fsync=av du kan också ställa in full_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 , eller pg_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.



  1. Hur man implementerar SQLCipher när man använder SQLiteOpenHelper

  2. Hur man får Oracle att skapa tabellsats i SQL*Plus

  3. Ansluter SQL Server till PostgreSQL

  4. dela strängen i flera rader