导入数据非常慢

时间:2015-06-16 21:40:14

标签: sql-server sql-server-2008 import

每个月我需要导入1-150万行归档数据。我首先将它导入临时表(Tasks $)然后运行存储过程以根据需要插入到永久表中。导入临时表只需几秒钟。但是,存储过程需要2-3个小时才能运行。有没有比我这样做更好的方法,或者这只是我正在尝试做的事情的本质,而且从长远来看是不可能的?

如果我在没有合并行的情况下运行它(没有STUFF / SELECT命令),它运行得非常快,所以我知道延迟都在哪里。

CREATE TABLE #Temp_DataArchive
(
    EmployeeID int,
    StartTime Time(0),
    Task nvarchar(25),
    Duration int,
    Details nvarchar(max),
    Weekdays nvarchar(max)
)

INSERT INTO #Temp_DataArchive
SELECT EmployeeID, StartTime, Task, Duration,
        STUFF((SELECT DISTINCT ', ' + A.Tasks FROM Tasks$ A
        WHERE (A.EmployeeID=B.EmployeeID) AND 
            (A.StartTime=B.StartTime) AND
            (A.Task=B.Task) AND
            (A.Duration=B.Duration)
        FOR XML PATH('')),1,1,'') As Details,
        STUFF((SELECT ', ' + A.Weekdays FROM Tasks$ A
        WHERE (A.EmployeeID=B.EmployeeID) AND 
            (A.StartTime=B.StartTime) AND
            (A.Task=B.Task) AND
            (A.Duration=B.Duration)
        FOR XML PATH('')),1,1,'') As Weekdays
FROM Tasks$ B
GROUP BY EmployeeID, StartTime, Task, Duration

为了完整起见,我应该补充说,在完成之后,我还需要将工作日转换为单独的位类型列,我使用以下内容,但这只需要几秒钟就可以运行。

INSERT INTO DataArchive
SELECT EmployeeID, StartTime, Task, Duration, Details,
    CASE WHEN Weekdays like '%Monday%' THEN 1 ELSE 0 END AS M,
    CASE WHEN Weekdays like '%Tuesday%' THEN 1 ELSE 0 END AS Tu,
    CASE WHEN Weekdays like '%Wednesday%' THEN 1 ELSE 0 END AS W,
    CASE WHEN Weekdays like '%Thursday%' THEN 1 ELSE 0 END AS Th,
    CASE WHEN Weekdays like '%Friday%' THEN 1 ELSE 0 END AS F,
    CASE WHEN Weekdays like '%Saturday%' THEN 1 ELSE 0 END AS Sa,
    CASE WHEN Weekdays like '%Sunday%' THEN 1 ELSE 0 END AS Su
FROM #Temp_DataArchive

drop table #Temp_DataArchive

编辑:解决方案 - 我在原始临时表(Tasks $)上缺少索引。添加了这些索引, #Temp_DataArchive 中的插入时间从2-3小时减少到2-3分钟。

2 个答案:

答案 0 :(得分:1)

使用如此多的数据进行XML处理会降低您的速度。

我不明白为什么你想把你的数据很好地解析成行并将它们放入逗号分隔的列表中。您没有获益,并且将来更难以查询。只需按原样导入行。如果您需要将它们组合在一个界面中的视图中,只需让客户端为他们查询的特定项目构建逗号列表。如果您正在尝试节省空间,可以为每个(EmployeeID,StartTime,Task,Duration)创建一个身份ID字段,然后为您的任务创建一个关系表(ID,Task)。

答案 1 :(得分:0)

直到我发布结果我才意识到你已经找到了解决方案(doi!)。我不会像我要去的那样对jibber-jabber的索引感到满意,但也给了这个格式一个机会。它对我来说通常更快,而且它是我的首选合成器风格。

请阅读有关使用STUFF / FOR XML的评论。

SELECT EmployeeID, Task, xtask.*, xdetail.*
FROM dbo.Task b
CROSS APPLY (
  SELECT [TaskList] = STUFF((
    SELECT DISTINCT
      N', ' + a.Task
    FROM dbo.Task a
    WHERE a.EmployeeID = b.EmployeeID
    FOR XML PATH(N''), TYPE
    -- Pull out the value from the xml or xml-escaped chars will stay escaped (ie. <>&)
    -- If you don't need to worry about that, you can remove this part to save a little time
  ).value(N'.', N'nvarchar(max)'), 1, 2, N'')
) xtask
CROSS APPLY (
  SELECT [DetailList] = STUFF((
    SELECT DISTINCT
      N', ' + a.Details
    FROM dbo.Task a
    WHERE a.EmployeeID = b.EmployeeID
    FOR XML PATH(N''), TYPE
  ).value(N'.', N'nvarchar(max)'), 1, 2, N'')
) xdetail
GROUP BY EmployeeID, Task