Python 在Psycopg2中高效插入大量行

Python 在Psycopg2中高效插入大量行,python,postgresql,psycopg2,Python,Postgresql,Psycopg2,我需要高效地将大约500k(给定或获取100k)行数据插入到我的PostgreSQL数据库中。经过大量的谷歌搜索,我得到了这个解决方案,平均约150秒(挂钟) 有没有更快的方法?我不知道.execute\u batch是否可以接受生成器,但您可以尝试以下方法: def db_insert_spectrum(curs, visual_data, recording_id): sql = """ INSERT INTO spectrums (row, col, value,

我需要高效地将大约500k(给定或获取100k)行数据插入到我的PostgreSQL数据库中。经过大量的谷歌搜索,我得到了这个解决方案,平均约150秒(挂钟)


有没有更快的方法?

我不知道
.execute\u batch
是否可以接受生成器,但您可以尝试以下方法:

def db_insert_spectrum(curs, visual_data, recording_id):
    sql = """
        INSERT INTO spectrums (row, col, value, recording_id)
        VALUES %s
    """
    data_gen =  ((rIdx, cIdx, value, recording_id) for rIdx, cData in enumerate(visual_data) 
                                               for cIdx, value in enumerate(cData))
    psycopg2.extras.execute_batch(curs, sql, data_gen, page_size=1000)
try:
    # Python2
    from cStringIO import StringIO 
except ImportError:
    # Python3
    from io import StringIO

def db_insert_spectrum(curs, visual_data, recording_id):
    f = StringIO()
    # visual_data is a 2D array (a nx63 matrix)
    values_list = []
    for rowIndex, rowData in enumerate(visual_data):
        items = []
        for colIndex, colData in enumerate(rowData): 
            value = (rowIndex, colIndex, colData, recording_id)
            items.append('\t'.join(map(str, value))+'\n')
        f.writelines(items)
    f.seek(0)
    cur.copy_from(f, 'spectrums', columns=('row', 'col', 'value', 'recording_id'))
它可能更快。

基于,是最快的方法<代码>复制读取文件或类似文件的对象

因为内存I/O比磁盘I/O快,所以将数据写入类似文件的对象比写入实际文件要快。 psycopg文档显示了使用
StringIO
作为输入进行调用的示例

因此,您可以使用以下内容:

def db_insert_spectrum(curs, visual_data, recording_id):
    sql = """
        INSERT INTO spectrums (row, col, value, recording_id)
        VALUES %s
    """
    data_gen =  ((rIdx, cIdx, value, recording_id) for rIdx, cData in enumerate(visual_data) 
                                               for cIdx, value in enumerate(cData))
    psycopg2.extras.execute_batch(curs, sql, data_gen, page_size=1000)
try:
    # Python2
    from cStringIO import StringIO 
except ImportError:
    # Python3
    from io import StringIO

def db_insert_spectrum(curs, visual_data, recording_id):
    f = StringIO()
    # visual_data is a 2D array (a nx63 matrix)
    values_list = []
    for rowIndex, rowData in enumerate(visual_data):
        items = []
        for colIndex, colData in enumerate(rowData): 
            value = (rowIndex, colIndex, colData, recording_id)
            items.append('\t'.join(map(str, value))+'\n')
        f.writelines(items)
    f.seek(0)
    cur.copy_from(f, 'spectrums', columns=('row', 'col', 'value', 'recording_id'))

在我问这个问题之前,我试着做一些类似的事情。当我尝试实现它时,我遇到了一个不同的错误。按照您的方式,错误是
psycopg2.DataError:integer的输入语法无效:“(0,0,0,71)”
行、列、值和录制id列都是intsAn早期版本的我使用的代码
value=[(行索引、列索引、列数据、录制id)]
。相反,拆下支架,如上所述。(您可能需要刷新您的网页。)我认为这应该可以修复错误。啊,是的,谢谢。有了这个改变,我已经到了尝试实现这个的时候。它给了我以下错误:
psycopg2.DataError:上次预期的列上下文之后的额外数据:复制频谱,第63行:“0 62 0 731 0 0 73”
您使用的是
f.writelines
?这也是我的一个错误——它缺少分隔行所需的
\n
s。再次确保已刷新网页,并尝试
f.write('\n'.join(items))
(请参见上文)。是!绝对惊人!非常感谢,现在只花了十分之一的时间!非常感谢你的帮助。我会向上投票的答案(除了选择作为答案),但我没有足够的代表…更快。而且对我来说更容易理解。更容易将为ExecuteMy编写的代码转换为这种样式。