SQL虽然Loop占用时间太长

时间:2013-10-03 15:59:10

标签: sql

经过几天的互联网搜索并试图改善这一点后,我终于决定寻求帮助。

我每天从一个包含大约110万行数据的客户端收到一个平面文件。我将此数据导入带有SSIS的临时数据库(SQL Server 2012)。这只需几秒钟。数据基本上是预约信息。

平面文件中有几个字段,但我必须使用它来同步报告表:

UpdateType - 包含INSERT,UPDATE或DELETE ChangeDate - 行更改时的日期时间戳 UniqueKey - UniqueKey + ChangeDate为行

创建唯一键

来自客户端的要求是我按照ChangeKate by UniqueKey的顺序INSERT,UPDATE或DELETE报告数据库中的行。我无法弄清楚如何在一个集合中做到这一点,所以我创建了一个while循环,运行时间超过20小时太长了。

以下是我收到的平面文件数据示例:

UpdateType   UniqueKey   ChangeDate              MoreDate
INSERT       27244595    2013-09-24 08:51:48.367 synchronize data follows
DELETE       27244595    2013-09-25 10:15:08.433 synchronize data follows
INSERT       27244595    2013-09-25 10:15:09.990 synchronize data follows
DELETE       27244595    2013-09-25 15:02:36.287 synchronize data follows
INSERT       27244595    2013-09-25 15:02:36.610 synchronize data follows

正如您所看到的那样,插入了相同的记录然后删除了多次,但情况并非总是如此。在此示例数据中,只有最后一条记录应出现在报告数据库表中,预定了1个约会。

以下是来自同一平面文件的另一个示例:

UpdateType   UniqueKey   ChangeDate              MoreDate
INSERT       28243572    2013-09-25 10:15:08.610 synchronize data follows
INSERT       28243572    2013-09-25 10:15:09.880 synchronize data follows
DELETE       28243572    2013-09-25 14:01:36.210 synchronize data follows
INSERT       28243572    2013-09-25 14:02:37.287 synchronize data follows

在此示例中,第一个和最后一个记录应出现在报告数据库表中。预约有2个约会。还有其他时候混合更新。

我不会创建报告,也不知道它们是什么样的。

这是我编写的用于从登台数据库同步报告数据库的代码。如果您对如何改进此流程有任何建议,我欢迎他们并感谢您的帮助。

DECLARE --DECLARE SOME VARIABLES TO USE IN THE LOOP
 @UPDATETYPE VARCHAR(6) --THIS WILL BE INSERT, DELETE OR UPDATE
,@KEY INTEGER --THIS IS THE UNIQUEKEY
,@CHANGEDATE DATETIME --THIS IS THE CHANGE DATE FROM THE FLATFILE

--START A WHILE LOOP TO GO ROW BY ROW 
WHILE (SELECT COUNT(*) FROM STAGEDB.DBO.APPIONTMENTCHANGE) > 0
    BEGIN

SELECT @UPDATETYPE = (SELECT TOP 1 [UPDATETYPE] FROM STAGEDB.DBO.APPIONTMENTCHANGE 
            ORDER BY [UNIQUEKEY], [CHANGEDATE]) --GET THE UPDATE TYPE FOR THE IF STATEMENTS

SELECT @KEY = (SELECT TOP 1 [UNIQUEKEY] FROM STAGEDB.DBO.APPIONTMENTCHANGE 
         ORDER BY [UNIQUEKEY], [CHANGEDATE]) --GET THE KEY

SELECT @CHANGEDATE = (SELECT TOP 1 [CHANGEDATE] FROM STAGEDB.DBO.APPIONTMENTCHANGE 
            ORDER BY [UNIQUEKEY], [CHANGEDATE]) --GET THE CHANGEDATE

--IF THIS ROW IS AN INSERT THEN COMPLETE THIS ON THE REPORT DATABASE
IF @UPDATETYPE = 'INSERT'
BEGIN
 INSERT INTO [REPORTDB].[DBO].[APPOINTMENT]
            ([REPORTDB].[DBO].[APPOINTMENT].[UNIQUEKEY]
            ,[REPORTDB].[DBO].[APPOINTMENT].[APPOINTMENT]
            ,[REPORTDB].[DBO].[APPOINTMENT].[CLIENTLEADBK]
            ,[REPORTDB].[DBO].[APPOINTMENT].[FIRSTNAME]
            ,[REPORTDB].[DBO].[APPOINTMENT].[LASTNAME]
            ,[REPORTDB].[DBO].[APPOINTMENT].[PHONENUMBER]
            ,[REPORTDB].[DBO].[APPOINTMENT].[PHONENUMBER2]
            ,[REPORTDB].[DBO].[APPOINTMENT].[PHONENUMBER3]
            ,[REPORTDB].[DBO].[APPOINTMENT].[PHONENUMBER4]
            ,[REPORTDB].[DBO].[APPOINTMENT].[ADDRESSSTREET]
            ,[REPORTDB].[DBO].[APPOINTMENT].[ADDRESSCITY]
            ,[REPORTDB].[DBO].[APPOINTMENT].[ADDRESSSTATE]
            ,[REPORTDB].[DBO].[APPOINTMENT].[ADDRESSZIP]
            ,[REPORTDB].[DBO].[APPOINTMENT].[ADDRESSCOUNTRY])
SELECT TOP 1 [UNIQUEKEY]
            ,[APPOINTMENT]
            ,[CLIENTLEADBK]
            ,[FIRSTNAME]
            ,[LASTNAME]
            ,[PHONENUMBER]
            ,[PHONENUMBER2]
            ,[PHONENUMBER3]
            ,[PHONENUMBER4]
            ,[ADDRESSSTREET]
            ,[ADDRESSCITY]
            ,[ADDRESSSTATE]
            ,[ADDRESSZIP]
            ,[ADDRESSCOUNTRY]
        FROM [STAGEDB].[DBO].[APPIONTMENTCHANGE] 
    ORDER BY [UNIQUEKEY], [CHANGEDATE];

--ONCE THE INSERT IS COMPLETED THEN DELETE THE ALREADY WORKED RECORD FROM THE STAGING DATABASE
DELETE FROM [STAGEDB].[DBO].[APPIONTMENTCHANGE] 
WHERE [UNIQUEKEY] = @KEY AND [CHANGEDATE] = @CHANGEDATE;

END

--IF THE ROW IS A DELETE REQUEST THEN COMPLETE THIS ON THE REPORT DATABASE
IF @UPDATETYPE = 'DELETE'
BEGIN

DELETE FROM [REPORTDB].[DBO].[APPOINTMENT]
WHERE [UNIQUEKEY] = @KEY AND [CHANGEDATE] = @CHANGEDATE;

--ONCE THE DELETE IS COMPLETED THEN DELETE THE ALREADY WORKED RECORD FROM THE STAGING DATABASE
DELETE FROM [STAGEDB].[DBO].[APPIONTMENTCHANGE] 
WHERE [UNIQUEKEY] = @KEY AND [CHANGEDATE] = @CHANGEDATE;

END

--IF THE ROW IS A UPDATE REQUEST DO THAT
IF @UPDATETYPE = 'UPDATE'
BEGIN

    UPDATE [REPORTDB].[DBO].[APPOINTMENT]
       SET [REPORTDB].[DBO].[APPOINTMENT].[APPOINTMENT] = B.[APPOINTMENT]
      ,[REPORTDB].[DBO].[APPOINTMENT].[CLIENTLEADBK] = B.[CLIENTLEADBK]
      ,[REPORTDB].[DBO].[APPOINTMENT].[FIRSTNAME] = B.[FIRSTNAME]
      ,[REPORTDB].[DBO].[APPOINTMENT].[LASTNAME] = B.[LASTNAME]
      ,[REPORTDB].[DBO].[APPOINTMENT].[PHONENUMBER] = B.[PHONENUMBER]
      ,[REPORTDB].[DBO].[APPOINTMENT].[PHONENUMBER2] = B.[PHONENUMBER2]
      ,[REPORTDB].[DBO].[APPOINTMENT].[PHONENUMBER3] = B.[PHONENUMBER3]
      ,[REPORTDB].[DBO].[APPOINTMENT].[PHONENUMBER4] = B.[PHONENUMBER4]
      ,[REPORTDB].[DBO].[APPOINTMENT].[ADDRESSSTREET] = B.[ADDRESSSTREET]
      ,[REPORTDB].[DBO].[APPOINTMENT].[ADDRESSCITY] = B.[ADDRESSCITY]
      ,[REPORTDB].[DBO].[APPOINTMENT].[ADDRESSSTATE] = B.[ADDRESSSTATE]
      ,[REPORTDB].[DBO].[APPOINTMENT].[ADDRESSZIP] = B.[ADDRESSZIP]
      ,[REPORTDB].[DBO].[APPOINTMENT].[ADDRESSCOUNTRY] = B.[ADDRESSCOUNTRY]
      FROM [REPORTDB].[DBO].[APPOINTMENT]
INNER JOIN [STAGEDB].[DBO].[APPIONTMENTCHANGE] B 
        ON [REPORTDB].[DBO].[APPOINTMENT].[UNIQUEKEY] = B.[UNIQUEKEY]
     WHERE [REPORTDB].[DBO].[APPOINTMENT].[UNIQUEKEY] = @KEY;

--ONCE THE UPDATE IS COMPLETED THEN DELETE THE ALREADY WORKED RECORD FROM THE STAGING DATABASE
DELETE FROM [STAGEDB].[DBO].[APPIONTMENTCHANGE] 
WHERE [UNIQUEKEY] = @KEY AND [CHANGEDATE] = @CHANGEDATE;
END
    END

我宁愿拥有所有需要插入的文件,所有这些都需要删除,所有这些都应该更新,而不是每次发生的记录更改,但这是我现在必须处理的。

赞赏所有改进的重要想法。请提供尽可能多的解释。

1 个答案:

答案 0 :(得分:0)

使用普通的sql命令。首先是插入

insert into realtable
(field1, field2, etc)
select field1, field2, etc
from stagingtable
where idfield in
(select idfield 
from stagingtable
except 
select idfield
from realtable)

更新

update r
set field1 = s.field1
, etc
from realtable r join stagingtable s on something
where whatever

缺失

delete from reatable
where idfield in
(select idfield
from staging table
where you want the record deleted from the real table)