psycopg2使用cursor.copy_from()复制大数据时卡死
考虑一下下面这段Python代码,它使用了psycopg2的cursor
对象(为了清晰起见,有些列名被更改或省略了):
filename='data.csv'
file_columns=('id', 'node_id', 'segment_id', 'elevated',
'approximation', 'the_geom', 'azimuth')
self._cur.copy_from(file=open(filename),
table=self.new_table_name, columns=file_columns)
- 这个数据库在一台远程机器上,连接速度很快。
- 在bash中使用
\COPY
命令导入数据非常快,即使是处理大约100万行的文件也没问题。
这段代码在处理5000行数据时非常快,但当data.csv
文件超过10000行时,程序就完全卡住了。
有什么想法或解决方案吗?
亚当
2 个回答
1
这是因为内存限制导致“copy_from”崩溃,因为使用open(filename)时会一次性读取整个文件。这是psycopg2的问题,不是Postgresql的问题,所以Mike的解决方案是最好的。
如果你想在使用“copy_from”的同时进行常规提交,并管理重复的键,有一个解决办法:https://stackoverflow.com/a/11059350/1431079
5
这只是一个临时解决办法,你可以把一些东西输入到psql里。我有时候会用这个方法,因为我懒得去用psycopg2。
import subprocess
def psql_copy_from(filename, tablename, columns = None):
"""Warning, this does not properly quote things"""
coltxt = ' (%s)' % ', '.join(columns) if columns else ''
with open(filename) as f:
subprocess.check_call([
'psql',
'-c', 'COPY %s%s FROM STDIN' % (tablename, coltxt),
'--set=ON_ERROR_STOP=true', # to be safe
# add your connection args here
], stdin=f)
关于你提到的卡住的问题,你是不是在用多个线程或者类似的东西?
你的postgres有没有记录一些信息,比如连接关闭或者死锁?在它卡住之后,你能看到磁盘有活动吗?