在Psycopg2中有效插入大量行

时间:2017-11-05 00:01:04

标签: python postgresql psycopg2

我需要有效地向我的PostgreSQL数据库插入大约500k(给出或接受100k)数据行。经过大量的谷歌搜索,我已经得到了这个解决方案,平均大约150(挂钟)秒。

def db_insert_spectrum(curs, visual_data, recording_id):
    sql = """
        INSERT INTO spectrums (row, col, value, recording_id)
        VALUES %s
    """

    # Mass-insertion technique
    # visual_data is a 2D array (a nx63 matrix)
    values_list = []
    for rowIndex, rowData in enumerate(visual_data):
        for colIndex, colData in enumerate(rowData): # colData is the value
            value = [(rowIndex, colIndex, colData, recording_id)]
            values_list.append(value)

    psycopg2.extras.execute_batch(curs, sql, values_list, page_size=1000)

有更快的方法吗?

2 个答案:

答案 0 :(得分:6)

基于answers given hereCOPY是最快的方法。 COPY从文件或类文件对象中读取。

由于内存I / O比磁盘I / O快many orders of magnitude,因此将数据写入类似StringIO文件的对象比写入实际文件更快。 psycopg文档显示了以StringIO作为输入调用copy_from的示例。

因此,你可以使用类似的东西:

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'))

答案 1 :(得分:0)

我不知道.execute_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) 它可能会更快。

相关问题