在我的设置中,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时导致字符串缓冲区错误。
我怀疑你的CSV格式不正确 - 或者更具体地说,不符合你在'COPY'命令中指定的格式。有关详细信息,请参见[CSV处理文档](http://www.postgresql.org/docs/current/static/sql-copy.html#AEN66692)。你的CSV有一个不匹配的'''字符吗? – willglynn
我认为它是单引号或双引号和字符串的问题。一些字符串值没有正确终止或文本值内有单个字符(例如...不是...),我敢打赌第二个。无论如何这就是为什么Postgres试图缓冲更大的字符串,然后它最初保存在csv文件中。 – Wojtas
我首先检查CSV文件中的(最大)行长度。 BTW:这是遗传/ DNA数据吗? – wildplasser