【发布时间】:2011-08-11 01:23:11
【问题描述】:
我正在编写一个 Django-ORM 增强功能,它尝试缓存模型并将模型保存推迟到事务结束。这一切都差不多完成了,但是我在 SQL 语法上遇到了一个意想不到的困难。
我不是什么 DBA,但据我了解,对于许多小型查询,数据库并不能真正有效地工作。很少有更大的查询会好得多。例如,最好使用大批量插入(比如一次 100 行)而不是 100 个单行。
现在,据我所知,SQL 并没有真正提供任何语句来对表执行批量更新。这个术语似乎令人困惑,所以我将解释我的意思。我有一个任意数据数组,每个条目描述表中的一行。我想更新表中的某些行,每行都使用数组中相应条目中的数据。这个想法与批量插入非常相似。
例如:我的表可能有两列 "id" 和 "some_col"。现在,描述批量更新数据的数组包含三个条目(1, 'first updated')、(2, 'second updated') 和(3, 'third updated')。更新前,该表包含以下行:(1, 'first')、(2, 'second')、(3, 'third')。
我偶然发现了这个帖子:
Why are batch inserts/updates faster? How do batch updates work?
这似乎可以满足我的要求,但是我无法真正弄清楚最后的语法。
我还可以删除所有需要更新的行,然后使用批量插入重新插入它们,但是我很难相信这实际上会表现得更好。
我使用 PostgreSQL 8.4,所以这里也可以使用一些存储过程。然而,由于我计划最终开源该项目,因此欢迎任何更多可移植的想法或方法在不同的 RDBMS 上做同样的事情。
后续问题:如何进行批量“insert-or-update”/“upsert”语句?
测试结果
我在 4 个不同的表中执行了 100 次 10 次插入操作(因此总共 1000 次插入)。我在带有 PostgreSQL 8.4 后端的 Django 1.3 上进行了测试。
这些是结果:
- 通过 Django ORM 完成的所有操作 - 每次通过 ~2.45 秒,
- 相同的操作,但不使用 Django ORM 完成 - 每次传递 ~1.48 秒,
- 仅插入操作,不向数据库查询序列值~0.72 秒,
- 仅插入操作,以 10 个块为单位执行(共 100 个块)~0.19 秒,
- 仅插入操作,一大块执行块~0.13 秒。
- 仅插入操作,每个块大约 250 条语句,~0.12 秒。
结论:在单个connection.execute()中执行尽可能多的操作。 Django 本身引入了大量开销。
免责声明:我没有引入除默认主键索引之外的任何索引,因此插入操作可能会因此运行得更快。
【问题讨论】:
-
+1 因为我了解到“upsert”是一个真实的词(它甚至在wikipedia 上)
-
你能告诉我们你正在运行的语句吗?我对“批量更新”一词有点困惑?你不能用一个 UPDATE 语句来做所有的更新吗?在 9.1 中,您还可以使用可写 CTE 在单个操作中执行 UPDATE 和 INSERT
标签: sql database postgresql insert sql-update