2012-12-16 174 views
5

在我的設置中,PostgreSQL 9.2.2在嘗試將大型csv文件加載到表中時似乎出錯。PostgreSQL加載大型csv文件到表中時遇到問題

的CSV文件的大小是〜9GB

下面是我用做批量加載的SQL語句:

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

這裏有一個幾分鐘後,我得到的錯誤:

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

我認爲緩衝區不能分配超過1GB,這使我認爲這可能是postgresql.conf問題。

這裏的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# 

沒有明確設置一個緩衝到1GB。

這是怎麼回事?即使解決方案是增加postgresql.conf中的緩衝區,爲什麼postgres似乎嘗試將單個副本調用中的整個csv文件批量加載到ram中?人們會認爲加載大型csv文件是一項常見任務;我不能成爲第一個遇到這個問題的人;所以我認爲postgres會處理分塊的負載,所以緩衝區限制從來沒有達到過。

作爲一種解決方法,我將csv拆分爲較小的文件,然後爲每個文件調用副本。這似乎工作正常。但這不是一個特別令人滿意的解決方案,因爲現在我必須維護要加載到postgres中的每個大型csv的拆分版本。必須有更合適的方式將大型csv文件批量加載到postgres中。

編輯1:我正在確保csv文件不以任何方式格式不正確。我正在通過嘗試將所有拆分csv文件加載到postgres中來完成此操作。如果全部都可以加載,那麼這表明這裏的問題不可能是由於csv文件格式錯誤造成的。我已經發現了一些問題。還不確定這些問題是否在嘗試加載大型csv時導致字符串緩衝區錯誤。

+1

我懷疑你的CSV格式不正確 - 或者更具體地說,不符合你在'COPY'命令中指定的格式。有關詳細信息,請參見[CSV處理文檔](http://www.postgresql.org/docs/current/static/sql-copy.html#AEN66692)。你的CSV有一個不匹配的'''字符嗎? – willglynn

+0

我認爲它是單引號或雙引號和字符串的問題。一些字符串值沒有正確終止或文本值內有單個字符(例如...不是...),我敢打賭第二個。無論如何這就是爲什麼Postgres試圖緩衝更大的字符串,然後它最初保存在csv文件中。 – Wojtas

+0

我首先檢查CSV文件中的(最大)行長度。 BTW:這是遺傳/ DNA數據嗎? – wildplasser

回答

5

原來是一個畸形的csv文件。

我把大的csv分成更小的塊(每個塊有100萬行),並開始將每個塊加載到postgres中。

我開始更多的信息錯誤:

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 

共有5列無效UTF-8字節序列,出幾百萬元的人。刪除這些行後,大9GB csv加載得很好。

最初在加載大文件時得到無效的字節序列錯誤本來是很好的。但至少他們在我開始孤立這個問題後就出現了。

請注意,最初加載大文件時錯誤中提到的行號與加載較小csv子集文件時發現的編碼錯誤沒有關係。初始行號是文件中發生1GB數據的點,因此與1GB緩衝區分配錯誤有關。但是,這個錯誤與真正的問題無關......

+0

您可能想要提交一個錯誤報告以獲取錯誤的錯誤消息 –

+0

Oracle也有更豐富的導入l sql * loader,它具有更強大的錯誤處理能力。使用Postgre我通常將所有數據加載到登臺表中,這些登臺表具有使用TEXT數據類型創建的所有列。這樣我就可以將所有的數據加載到數據庫中,然後運行不同的查詢來查找數據問題。 – Kuberchaun

+0

順便說一句,它需要多長時間從這樣一個大文件複製數據postgres? – DataGreed