在 Psycopg2 中高效地插入大量行
Efficiently insert massive amount of rows in Psycopg2
我需要高效地将大约 500k(大约 100k)行数据插入到我的 PostgreSQL 数据库中。经过大量 google-ing,我得到了这个解决方案,平均大约 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)
有没有更快的方法?
我不知道 .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)
它可能会更快。
基于answers given here, COPY是最快的方法。 COPY
从文件或类文件对象中读取。
因为内存 I/O 是 many orders of magnitude faster than disk I/O, it is faster to write the data to a 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'))
我需要高效地将大约 500k(大约 100k)行数据插入到我的 PostgreSQL 数据库中。经过大量 google-ing,我得到了这个解决方案,平均大约 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)
有没有更快的方法?
我不知道 .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)
它可能会更快。
基于answers given here, COPY是最快的方法。 COPY
从文件或类文件对象中读取。
因为内存 I/O 是 many orders of magnitude faster than disk I/O, it is faster to write the data to a 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'))