En av utmaningarna när du hanterar en ny databasdesign är att du inte vet saker som hur stora tabellerna kommer att bli förrän de faktiskt är fyllda med en hel del data. Men om designen måste ta hänsyn till eventuella skalbarhetsproblem, kan du inte distribuera den för att erhålla dessa data förrän uppskattningen är gjord. Ett sätt runt detta är att aggressivt prototyper saker. Använd iscensättningshårdvara för detta ändamål som nya applikationer kan leva på tillfälligt medan du sorterar bort detaljer som denna. Du kan bara räkna med att du måste flytta appen och eventuellt göra om den efter några månader, när du har en bättre uppfattning om vilken data som kommer att dyka upp i den.
Det andra sättet att komma runt detta kyckling-/äggproblem är att skriva en datagenerator. Konstruera tillräckligt med exempeldata för hand för att se hur det ser ut, hur tätt det är och hur dess värden är fördelade. Skriv sedan något som tar den statistiken och producerar en större datauppsättning liknande den. Du kommer aldrig att få det att vara perfekt, men det behöver inte vara det. Att generera gigantiska datamängder, även med vissa brister, är fortfarande det bästa tillgängliga sättet att göra uppskattning av databasstorlek. Det finns så många källor till overhead att det är svårt att ta hänsyn till att alla uppmätta tabell- och indexstorlekar, baserat på något som dina data, kommer att vara mycket mer exakta än någon annan metod. Det finns en anledning till att jag slutar svara på många frågor om prestandarelaterade problem genom att använda pgbench för att skapa en databas av lämplig storlek först.
Datagenerering är dock inte lätt. Att skapa realistiska tidsstämplar i synnerhet är alltid irriterande. Och oavsett hur effektivt du tror att du har skrivit dem, tar de vanligtvis längre tid än du förväntar dig att köra – och ännu längre tid att få den resulterande informationen i en databas och korrekt indexerad.
Och det fortsätter att vara fallet oavsett hur många gånger du har gjort detta, för även om du gör allt rätt kommer Murphys lag att inkräkta för att göra jobbet smärtsamt oavsett. Mina datorer hemma är alla byggda av relativt billig PC-hårdvara. Inte de billigaste sakerna som finns – jag har standarder – men jag använder absolut inte samma kvalitet som jag skulle rekommendera folk att leta efter på en server. Veckans problem med datagenerering påminde om varför bättre hårdvara är värd hur mycket den kostar för affärskritiskt arbete.
Efter att ha genererat några miljarder rader med data och sett importen i 10 timmar, var jag inte nöjd med att få hela jobbet avbryta så här:
psql:load.sql:10: ERROR: invalid input syntax for type timestamp: "201^Q-04-14 12:17:55"
CONTEXT: COPY testdata, line 181782001, column some_timestamp: "201^Q-04-14 12:17:55"
Det visade sig att någonstans mitt under skrivningen av de 250 GB testdata som jag genererade var en av radernas utdata skadad. Två bitar vände, och data som skrevs ut var fel. Jag vet inte var det hände med säkerhet.
Minne är den mest troliga misstänkta. Riktiga servrar använder ECC RAM, och det av goda skäl. Om du övervakar ett system med mycket RAM-minne kan antalet fel som tyst korrigeras av ECC vara chockerande. RAM-minnet jag använder hemma är bra, men felfrekvensen på vilket minne som helst utan feldetekterings-/korrigeringsmöjligheter kommer att vara högre än vad du kanske vill – och upptäcks aldrig om de inte sker i kod som leder till en systemkrasch. Datagenereringsarbete är bra på att avslöja dessa problem, eftersom det vanligtvis sätter minst en CPU på din server under hård belastning för potentiellt dagar i rad. Om det finns någon instabilitet i ditt system, kommer det att förvärras av att få systemet varmt och låta det gå under lång tid.
Ett andra lager av skydd mot denna typ av korruption är att lägga kontrollsummor på data som skrivs till disken, för att skydda mot fel som skriver och sedan läser data tillbaka igen. Blockkontrollsumman som görs av ZFS-filsystemet är en av de bättre implementeringarna av det. I mitt fall kan det inte ha gjort någon skillnad om jag hade använt ZFS eller inte. Om bitarna vändes innan blockkontrollsumman inträffade, skulle jag ha skrivit ut skräpdata – med en skräpkontrollsumma för att matcha den – oavsett.
Mitt nästa steg var att använda split verktyg för att ta min gigantiska fil och dela upp den i mer lagom stora bitar – ytterligare ett par timmar att vänta på att det ska bli klart. Sedan kunde jag börja ladda de bra filerna medan jag fixade den dåliga.
Med tanke på att de resulterande filerna var 13 GB var och min ena server har 16 GB RAM, även om jag kunde fixa detta ena teckenstavfel med vi. Teoretiskt borde det vara fallet, men jag börjar ha mina tvivel med tanke på hur länge jag har väntat på att filen ska skrivas ut igen efteråt:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
21495 gsmith 20 0 8542m 8.3g 1544 R 98 53.0 419:56.70 vi datafile-ag
Det är en fast 7 timmar som jag har väntat bara på att det här stavfelet med ett tecken ska fixas, så jag kan slutföra att ladda testdatan. Som jag sa, seriös datagenerering är aldrig lätt.