2012-12-16 18 views
5

Podczas mojej instalacji PostgreSQL 9.2.2 wydaje się być pomyłką podczas próby załadowania dużego pliku csv do tabeli.Kłopoty z PostgreSQL ładowaniem dużego pliku CSV do tabeli

Wielkość pliku csv jest ~ 9GB

Oto SQL używam zrobić ładunek luzem:

copy chunksBase (chunkId, Id, chunk, chunkType) from path-to-csv.csv' delimiters ',' csv 

tu jest błąd pojawia się po kilku minutach:

pg.ProgrammingError: ERROR: out of memory 
DETAIL: Cannot enlarge string buffer containing 1073723635 bytes by 65536 more bytes. 
CONTEXT: COPY chunksbase, line 47680536 

Myślę, że bufor nie może przydzielić więcej niż dokładnie 1 GB, co powoduje, że myślę, że może to być problem postgresql.conf.

oto komentarzem wierszy w postgresql.conf:

bash-3.2# cat postgresql.conf | perl -pe 's/^[ \t]*//' | grep -v '^#' | sed '/^$/d' 
log_timezone = 'US/Central' 
datestyle = 'iso, mdy' 
timezone = 'US/Central' 
lc_messages = 'en_US.UTF-8'   # locale for system error message 
lc_monetary = 'en_US.UTF-8'   # locale for monetary formatting 
lc_numeric = 'en_US.UTF-8'   # locale for number formatting 
lc_time = 'en_US.UTF-8'    # locale for time formatting 
default_text_search_config = 'pg_catalog.english' 
default_statistics_target = 50 # pgtune wizard 2012-12-02 
maintenance_work_mem = 768MB # pgtune wizard 2012-12-02 
constraint_exclusion = on # pgtune wizard 2012-12-02 
checkpoint_completion_target = 0.9 # pgtune wizard 2012-12-02 
effective_cache_size = 9GB # pgtune wizard 2012-12-02 
work_mem = 72MB # pgtune wizard 2012-12-02 
wal_buffers = 8MB # pgtune wizard 2012-12-02 
checkpoint_segments = 16 # pgtune wizard 2012-12-02 
shared_buffers = 3GB # pgtune wizard 2012-12-02 
max_connections = 80 # pgtune wizard 2012-12-02 
bash-3.2# 

Nic, co wyraźnie ustawia bufor do 1GB.

Co tu się dzieje? Nawet jeśli rozwiązaniem jest zwiększenie bufora w postgresql.conf, dlaczego postgres wydaje się próbować załadować cały plik csv do pamięci RAM w pojedynczej kopii? Można by pomyśleć, że ładowanie dużych plików CSV jest częstym zadaniem; Nie mogę być pierwszą osobą, która natrafi na ten problem; więc wyobrażam sobie, że postgres poradziłby sobie z ładowaniem zbiorczym, tak że nigdy nie osiągnięto limitu bufora.

Jako obejście problemu dzielę pliki CSV na mniejsze pliki, a następnie wywołując kopię dla każdego pliku. Wydaje się, że działa dobrze. Ale nie jest to szczególnie satysfakcjonujące rozwiązanie, ponieważ teraz muszę zachować podzielone wersje każdego dużego CSV, który chcę załadować do PostgreSQL. Musi istnieć bardziej odpowiedni sposób na ładowanie dużego pliku CSV do PostgreSQL.

EDIT1: Jestem w trakcie upewniania się, że plik csv nie jest w jakikolwiek sposób zniekształcony. Robię to, próbując załadować wszystkie podzielone pliki CSV na postgreSy. Jeśli wszystko może być załadowane, oznacza to, że problem tutaj nie jest prawdopodobny, ponieważ plik csv jest zniekształcony. Znalazłem już kilka problemów. Nie jestem jeszcze pewien, czy problemy te powodują błąd bufora ciągów podczas próby załadowania dużego pliku CSV.

+1

Podejrzewam, że plik CSV jest zniekształcony - lub dokładniej, nie odpowiada formatowi określonemu w komendzie 'COPY'. Więcej informacji można znaleźć w [dokumentacji dotyczącej obsługi CSV] (http://www.postgresql.org/docs/current/static/sql-copy.html#AEN66692). Czy Twój CSV ma niedopasowaną '' 'znakową? – willglynn

+0

Myślę, że jest to problem z pojedynczymi lub podwójnymi cudzysłowami i ciągami.Niektóre wartości ciągów nie są poprawnie zakończone lub istnieją pojedyncze znaki wewnątrz wartości tekstowych (np. ... nie są ...), założyłbym się o drugie, w każdym razie dlatego Postgres próbuje buforować większy ciąg, a następnie jest zapisany w pliku csv – Wojtas

+0

Najpierw sprawdziłem (maksymalną) długość linii w pliku CSV. BTW: czy to jest dane genetyczne/DNA? – wildplasser

Odpowiedz

5

Okazało się, że plik CSV jest zniekształcony.

Dzielę duże csv na mniejsze części (każda z 1 milionem wierszy) i zacząłem ładować każdą z nich do postgresu.

zacząłem coraz więcej błędów informacyjnych:

pg.ProgrammingError: ERROR: invalid byte sequence for encoding "UTF8": 0x00 
CONTEXT: COPY chunksbase, line 15320779 

pg.ProgrammingError: ERROR: invalid byte sequence for encoding "UTF8": 0xe9 0xae 0x22 
CONTEXT: COPY chunksbase, line 369513 

pg.ProgrammingError: ERROR: invalid byte sequence for encoding "UTF8": 0xed 0xaf 0x80 
CONTEXT: COPY chunksbase, line 16602 

Było w sumie 5 wierszy z nieprawidłowych sekwencji utf8 bajtów, spośród kilkuset milionów dolarów. Po usunięciu tych wierszy ładowanie csv o pojemności 9 GB jest w porządku.

Byłoby miło uzyskać błędne sekwencje bajtów podczas ładowania dużego pliku na początku. Ale przynajmniej pojawiły się, gdy zacząłem izolować problem.

Należy zauważyć, że numer linii wspomniany w błędzie podczas początkowego ładowania dużego pliku nie miał związku z błędami kodowania, które zostały znalezione podczas ładowania mniejszych plików podzbiorów CSV. Początkowy numer wiersza był punktem w pliku, w którym miało miejsce dokładnie 1 GB danych, więc był powiązany z błędem przydziału bufora 1 GB. Ale ten błąd nie miał nic wspólnego z rzeczywistym problemem ...

+0

Być może zechcesz zgłosić raport błędu dotyczący błędnego komunikatu o błędzie –

+0

Oracle ma również znacznie bogatszy import l sql * loader, który ma bardziej niezawodną obsługę błędów. w Postgre zazwyczaj ładuję wszystkie moje dane do tabel pomostowych, które mają wszystkie kolumny utworzone za pomocą typu danych TEXT. W ten sposób mogę załadować wszystkie dane do bazy danych, a następnie uruchomić różne zapytania w celu znalezienia problemów z danymi. – Kuberchaun

+0

BTW, jak długo zajmuje postgres do kopiowania danych z tak dużego pliku? – DataGreed

Powiązane problemy