Python 在Psycopg2中高效插入大量行
我需要高效地将大约500k(给定或获取100k)行数据插入到我的PostgreSQL数据库中。经过大量的谷歌搜索,我得到了这个解决方案,平均约150秒(挂钟)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,
有没有更快的方法?我不知道
.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编写的代码转换为这种样式。