psycopg2使用cursor.copy_from()复制大数据时卡死

0 投票
2 回答
8000 浏览
提问于 2025-04-16 02:51

考虑一下下面这段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有没有记录一些信息,比如连接关闭或者死锁?在它卡住之后,你能看到磁盘有活动吗?

撰写回答