42

我正在寻找将数百万个元组批量插入数据库的最有效方法。我正在使用 Python、PostgreSQL 和psycopg2

我已经创建了一个长长的 tulpes 列表,这些 tulpes 应该插入到数据库中,有时使用几何等修饰符Simplify

天真的方法是对INSERT语句列表进行字符串格式化,但我读过其他三种方法:

  1. 使用pyformat绑定样式进行参数插入
  2. 在元组列表上使用executemany,以及
  3. 使用将结果写入文件并使用COPY.

似乎第一种方法是最有效的,但我会很感激你的见解和代码片段告诉我如何正确地做到这一点。

4

9 回答 9

15

是的,我会投票支持 COPY,前提是您可以将文件写入服务器的硬盘驱动器(而不是运行应用程序的驱动器),因为 COPY 只会读取服务器。

于 2010-02-16T09:41:02.043 回答
11

有一个新的psycopg2 手册包含所有选项的示例。

COPY选项是最有效的。然后是死刑犯。然后用pyformat执行。

于 2010-02-16T10:18:57.273 回答
8

以我的经验executemany,并不比自己运行许多插入快,最快的方法是自己格式化INSERT具有许多值的单个,也许将来executemany会改进,但现在它很慢

我将 a 子类list化并重载 append 方法,因此当列表达到一定大小时,我格式化 INSERT 以运行它

于 2014-02-02T12:14:24.060 回答
7

您可以使用新的 upsert 库

$ 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'}setterdict{ 'age': 28, 'state': 'WI' }

几乎与编写自定义 INSERT[/UPDATE] 代码并直接使用 ... 运行它一样快,psycopg2并且如果该行已经存在,它就不会崩溃。

于 2012-09-27T01:27:02.230 回答
3

任何使用 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 直接连接在一起。

于 2018-01-02T02:06:31.173 回答
2

经过一些测试,unnest通常似乎是一个非常快速的选择,正如我从 @Clodoaldo Neto对类似问题的回答中了解到的那样。

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

但是,对于非常大的数据可能会很棘手

于 2015-12-31T09:18:01.400 回答
1

第一个和第二个将一起使用,而不是单独使用。第三个将是最有效的服务器,因为服务器将完成所有艰苦的工作。

于 2010-02-16T09:39:15.527 回答
0

一个非常相关的问题:使用 SQLAlchemy ORM 进行批量插入


条条大路通罗马,但其中一些穿越山脉,需要渡轮,但如果您想快速到达那里,只需走高速公路即可。


在这种情况下,高速公路将使用psycopg2的execute_batch()功能。文档说得最好:

当前的实现executemany()是(使用非常慈善的轻描淡写)不是特别执行。这些函数可用于加速针对一组参数的语句的重复执行。通过减少服务器往返次数,性能可以比使用executemany().

在我自己的测试execute_batch()中,它的速度大约是 的两倍executemany()并提供了配置 page_size 以进行进一步调整的选项(如果您想从驱动程序中挤出最后 2-3% 的性能)。

如果您使用 SQLAlchemy,则可以通过use_batch_mode=True在实例化引擎时设置为参数来轻松启用相同的功能create_engine()

于 2018-06-13T14:27:06.030 回答
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()
于 2021-03-23T20:47:58.730 回答