我正在寻找将数百万个元组批量插入数据库的最有效方法。我正在使用Python,PostgreSQL和psycopg2。
我创建了一长串应该插入数据库的tulpes,有时使用几何Simplify
等修饰符。
这种天真的方式是将INSERT
语句列表字符串格式化,但我读过其他三种方法:
pyformat
binding style进行参数化插入executemany
,COPY
。似乎第一种方式效率最高,但我很感激您的见解和代码片段,告诉我如何正确地做到这一点。
答案 0 :(得分:14)
是的,我会投票给COPY,前提是您可以将文件写入服务器的硬盘(而不是应用程序运行的驱动器),因为COPY只能读取服务器。
答案 1 :(得分:10)
有一个新的psycopg2 manual包含所有选项的示例。
COPY选项效率最高。然后是executemany。然后使用pyformat执行。
答案 2 :(得分:8)
根据我的经验executemany
并不比自己运行多个插件快得多,
最快的方法是自己格式化具有多个值的单个INSERT
,也许将来executemany
会有所改善,但现在它很慢
我继承了list
并重载了append方法,所以当列表达到一定大小时,我会格式化INSERT来运行它
答案 3 :(得分:6)
您可以使用a new upsert library:
$ pip install upsert
(您可能必须先pip install decorator
)
conn = psycopg2.connect('dbname=mydatabase')
cur = conn.cursor()
upsert = Upsert(cur, 'mytable')
for (selector, setter) in myrecords:
upsert.row(selector, setter)
其中selector
是dict
对象,{'name': 'Chris Smith'}
和setter
,dict
是{ 'age': 28, 'state': 'WI' }
几乎与编写自定义INSERT [/ UPDATE]代码并直接使用psycopg2
运行代码一样快......如果该行已经存在,它将不会爆炸。< / p>
答案 4 :(得分:1)
第一个和第二个将一起使用,而不是单独使用。第三个是服务器方面最有效的,因为服务器会所有努力工作。
答案 5 :(得分:1)
经过一些测试,unnest通常似乎是一个非常快的选择,因为我从 @Clodoaldo Neto 的answer中学到了类似的问题。
data = [(1, 100), (2, 200), ...] # list of tuples
cur.execute("""CREATE TABLE table1 AS
SELECT u.id, u.var1
FROM unnest(%s) u(id INT, var1 INT)""", (data,))
答案 6 :(得分:1)
使用SQLalchemy的任何人都可以尝试1.2版本,当使用use_batch_mode = True初始化引擎时,添加了对批量插入的支持以使用psycopg2.extras.execute_batch()而不是executemany:
engine = create_engine(
"postgresql+psycopg2://scott:tiger@host/dbname",
use_batch_mode=True)
http://docs.sqlalchemy.org/en/latest/changelog/migration_12.html#change-4109
然后有人必须使用SQLalchmey不会费心去尝试sqla和psycopg2的不同组合并将SQL直接组合在一起。
答案 7 :(得分:0)
一个非常相关的问题:Bulk insert with SQLAlchemy ORM
所有道路通往罗马,但其中一些穿越山脉,需要渡轮,但如果您想快速到达那里,只需走高速公路。
在这种情况下,高速公路将使用execute_batch()的psycopg2功能。文档说它是最好的:
executemany()
的当前实施(使用非常慈善的轻描淡写)并不是特别有效。这些函数可用于加速针对一组参数重复执行语句。通过减少服务器往返次数,性能可以比使用executemany()
好几个数量级。
在我自己的测试中execute_batch()
大约是executemany()
的两倍,并提供了配置page_size以进一步调整的选项(如果你想挤压最后一个)驱动程序性能的2-3%。)
使用use_batch_mode=True
create_engine()
设置为参数来使用SQLAlchemy,可以轻松启用相同的功能
答案 8 :(得分:0)
插入许多项目的最新方法是使用 execute_values
助手 (https://www.psycopg.org/docs/extras.html#fast-execution-helpers)。
from psycopg2.extras import execute_values
insert_sql = "INSERT INTO table (id, name, created) VALUES %s"
# this is optional
value_template="(%s, %s, to_timestamp(%s))"
cur = conn.cursor()
items = []
items.append((1, "name", 123123))
# append more...
execute_values(cur, insert_sql, items, value_template)
conn.commit()