在“选择然后更新”的情况下,如何避免再次获取数据

时间:2012-08-21 07:59:55

标签: sql sql-server performance sql-server-2008

目前,我的表(表A)有大约10.000.000条记录。每天都有100条记录。它们是新的,未经处理。因此,Process column = 0.我正在使用SQL Server 2008。

在我的业务中,我需要做两个步骤:

  1. 获取数据是新的(Process = 0),执行某些操作,然后插入表B.
  2. 在表A更新流程= 1。
  3. 所以,在第1步,我用WHERE子句获取它们来获取这100条记录。 在第2步,我必须再次使用WHERE子句来获取和更新它们。

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

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

    非常感谢。

3 个答案:

答案 0 :(得分:3)

考虑OUTPUT子句:

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

请注意,according to the manualB表不能:

  
      
  • 已启用定义的触发器。

  •   
  • 参与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
;

答案 1 :(得分:2)

SQL Server保存缓存中先前查询的结果。因此,如果您有有用的主键(例如:小型,群集代理键),则第二个查询不应成为问题。

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

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

答案 2 :(得分: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