2

目前,我的表(表 A)有大约 10.000.000 条记录。每天都有100条记录来。它们是新的,没有经过处理。所以,进程列 = 0。我使用的是 SQL Server 2008。

在我的业务中,我需要执行 2 个步骤:

  1. 获取数据是新的(Process = 0),做一些事情,然后插入到表 B 中。
  2. 在表 A 中更新进程 = 1。

因此,在第 1 步中,我使用 WHERE 子句获取这 100 条记录。在第 2 步,我必须再次使用 WHERE 子句来获取和更新它们。

我认为,两次获取数据,性能不会很好,对吧?

有人可以告诉我在这种情况下我应该怎么做,以便我只需要查询一次吗?

非常感谢。

4

3 回答 3

3

考虑 OUTPUT 子句:

UPDATE A
SET    Process = 1
OUTPUT INSERTED.column1,
       INSERTED.column2,
       …
INTO   B (column1, column2, …)
WHERE  Process = 0
;

请注意,根据手册,该B表不能:

  • 已启用在其上定义的触发器。

  • 参与 FOREIGN KEY 约束的任一侧。

  • 有 CHECK 约束或启用规则。

如果上述关于表的任何情况都是正确的B,那么您可以在最终将数据插入之前使用临时表或表变量作为中间存储B

DECLARE @newdata TABLE (columns);
UPDATE A
SET    Process = 1
OUTPUT INSERTED.column1,
       INSERTED.column2,
       …
INTO   @newdata (column1, column2, …)
WHERE  Process = 0
;
INSERT INTO B (columns)
SELECT columns FROM @newdata
;
于 2012-08-21T08:36:12.703 回答
2

SQL 服务器将先前查询的结果保存在缓存中。因此,如果您有有用的主键(例如:小的集群代理键),那么第二个查询应该不是问题。

如果您想创建更大的批次(例如一次 10000 个项目),您可以使用临时表来存储您在批次中处理的主键。这样,您不需要在查询中传递太多键。

避免过早优化。首先确定性能问题——如果有的话。

于 2012-08-21T08:36:04.870 回答
0

您可以使用触发器来解决您的问题:

CREATE TRIGGER TR_A ON  A
   AFTER INSERT
AS BEGIN
    INSERT INTO B (Column1, Column2, ...)
    SELECT I.Column1, I.Column2, ...
    FROM INSERTED I
    WHERE I.Process = 1
END
于 2012-08-28T06:22:53.223 回答