为什么批量插入/更新更快?批量更新如何工作?

时间:2009-06-17 13:20:09

标签: sql rdbms

为什么批量插入更快?是因为插入单行的连接和设置开销对于一组行是相同的吗?还有哪些因素会使批量插入更快?

批量更新如何运作?假设表没有唯一性约束,则insert语句对批处理中的其他insert语句实际上没有任何影响。但是,在批量更新期间,更新可能会更改表的状态,因此可能会影响批处理中其他更新查询的结果。

我知道批量插入查询的语法是在一个大查询中包含所有插入值。批量更新查询如何?对于例如如果我有单一的表单更新查询:

update <table> set <column>=<expression> where <condition1>
update <table> set <column>=<expression> where <condition2>
update <table> set <column>=<expression> where <condition3>
update <table> set <column>=<expression> where <condition4>

批量使用时会发生什么。单个查询会是什么样的?

批量插入&amp;更新SQL标准的一部分?

4 个答案:

答案 0 :(得分:27)

  

为什么批量插入更快?

由于种种原因,但主要的三个是:

  • 不需要重新分析查询。
  • 这些值在一次往返服务器中传输
  • 命令在单个事务中
  

是否因为插入单行的连接和设置开销对于一组行是相同的?

部分是,见上文。

  

批量更新如何运作?

这取决于RDBMS

Oracle中,您可以将所有值作为集合传输,并将此集合用作JOIN中的表格。

PostgreSQLMySQL中,您可以使用以下语法:

INSERT
INTO    mytable
VALUES 
        (value1),
        (value2),
        …

您也可以准备一次查询并在某种循环中调用它。通常有一些方法可以在客户端库中执行此操作。

  

假设表没有唯一性约束,insert语句对批处理中的其他insert语句实际上没有任何影响。但是,在批量更新期间,更新可能会更改表的状态,因此可能会影响批处理中其他更新查询的结果。

是的,您可能会或可能不会从这种行为中受益。

  

我知道批量插入查询的语法是在一个大查询中包含所有插入值。批量更新查询如何?

Oracle中,您在联接中使用集合:

MERGE
INTO    mytable
USING   TABLE(:mycol)
ON      …
WHEN MATCHED THEN
UPDATE
SET     …

PostgreSQL

UPDATE  mytable
SET     s.s_start = 1
FROM    (
        VALUES
        (value1),
        (value2),
        …
        ) q
WHERE   …

答案 1 :(得分:24)

我正在寻找关于“批量/批量”更新的同一主题的答案。人们经常通过将插入子句与多个值集(“批量”部分)进行比较来描述问题。

INSERT INTO mytable (mykey, mytext, myint)
VALUES 
  (1, 'text1', 11),
  (2, 'text2', 22),
  ...

明确的答案仍然避开我,但我在这里找到了解决方案:http://www.postgresql.org/docs/9.1/static/sql-values.html

说清楚:

UPDATE mytable
SET 
  mytext = myvalues.mytext,
  myint = myvalues.myint
FROM (
  VALUES
    (1, 'textA', 99),
    (2, 'textB', 88),
    ...
) AS myvalues (mykey, mytext, myint)
WHERE mytable.mykey = myvalues.mykey

它具有与“批量”相同的属性,即包含大量数据和一个语句。

答案 2 :(得分:4)

其他帖子解释了为什么批量陈述更快以及如何使用字面值来实现。

我认为知道如何使用占位符进行操作非常重要。不使用占位符可能会导致巨大的命令字符串,引用/转义错误,从而导致易于SQL注入的应用程序。

在PostgreSQL中使用占位符批量插入&gt; = 9.1

要在表“mytable”中插入任意数量的行,包括“col1”,“col2”和“col3”列,所有这些都得到了(一个语句,一个事务):

INSERT INTO mytable (col1, col2, col3)
 VALUES (unnest(?), unnest(?), unnest(?))

您需要为此语句提供三个参数。第一个必须包含第一列的所有值,依此类推。因此,所有参数都必须是长度相等的列表/向量/数组。

使用PostgreSQL中的占位符进行批量更新&gt; = 9.1

比方说,你的桌子被称为“mytable”。它由“key”和“value”列组成。

update mytable 
  set value = data_table.new_value
  from 
    (select unnest(?) as key, unnest(?) as new_value) as data_table
  where mytable.key = data_table.key

我知道,这不容易理解。它看起来像混淆的SQL。另一方面:它工作,它可以扩展,它可以在没有任何字符串连接的情况下工作,它是安全的,而且速度非常快。

您需要为此语句提供两个参数。第一个必须是包含列“key”的所有值的列表/向量/数组。当然,第二个必须包含列“值”的所有值。

如果达到大小限制,您可能需要查看COPY INTO ... FROM STDIN(PostgreSQL)。

答案 3 :(得分:0)

在批量更新中,数据库对一组数据起作用,逐行更新它必须运行与行相同的命令。因此,如果您在批处理中插入一百万行,则命令将被发送并处理一次,并且在逐行更新中,它将被发送和处理一百万次。这也是您永远不想在SQL Server或相关子查询中使用游标的原因。

SQL Server中基于集合的更新的示例:

update mytable
set myfield = 'test'
where myfield is null

这将在一步中更新所有100万条空值的记录。游标更新(这是以非批处理方式更新一百万行的方式)将一次遍历每一行并更新它。

批量插入的问题是批次的大小。如果您尝试一次更新太多记录,数据库可能会在该过程的持续时间内锁定该表,从而锁定所有其他用户。所以你可能需要做一个循环,一次只占批处理的一部分(但是几乎任何时候大于一行的数字都会比一次一行快)这比更新或插入或删除更慢整批,但比逐行操作更快,并且在用户没有尝试查看和更新​​同一表中的其他记录时,在具有许多用户且几乎没有可用停机时间的生产环境中可能需要。批处理的大小在很大程度上取决于数据库结构和确切的情况(带有触发器和许多约束的表比具有大量字段的表更慢,因此需要更小的批处理。)