在我的设置中,当尝试将大型csv文件加载到表中时,PostgreSQL 9.2.2似乎出错了。
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拆分为较小的文件,然后为每个文件调用copy。这似乎工作正常。但它不是一个特别令人满意的解决方案,因为现在我必须维护每个大型csv的拆分版本,我想加载到postgres中。必须有一种更合适的方法将大型csv文件批量加载到postgres中。
EDIT1:我正在确保csv文件没有任何形式的格式错误。我这样做是通过尝试将所有拆分csv文件加载到postgres中。如果可以加载所有内容,则表明此处的问题不太可能是由于csv文件格式错误。我已经发现了一些问题。在尝试加载大型csv时,还不确定这些问题是否导致字符串缓冲区错误。
答案 0 :(得分:7)
原来是一个格式错误的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行具有无效的utf8字节序列,其中有几亿行。删除这些行后,大的9GB csv加载就好了。
最初加载大文件时,获得无效的字节序列错误会很不错。但至少他们出现了我开始孤立问题。
请注意,最初加载大文件时错误中提到的行号与加载较小csv子集文件时发现的编码错误无关。初始行号是文件中恰好发生1GB数据的点,因此它与1GB缓冲区分配错误有关。但是,这个错误与真正的问题无关......