2016-06-24 78 views
0

我有一张表跨越2亿条记录,我试图运行下面的查询。该查询尝试根据上一条记录的时间戳更新表。无论如何,这个查询运行得更快吗?调整交叉记录更新查询

UPDATE [dbo].[Location Data] 
    SET [timestamp_prev] = 
    (
      SELECT [timestamp] FROM [dbo].[Location Data] newTable 
       WHERE [dbo].[Location Data].[RowNumber] = (newTable.[RowNumber] + 1) 
       AND [dbo].[Location Data].[mmsi] = newTable.[mmsi] 
    ); 
+0

检查您的查询计划:它实际上执行相关的子查询,还是将它转换为自连接?如果没有,你应该这样做。 – Blorgbeard

+0

您使用的是哪个版本的'SQL Server' –

回答

2

你可以尝试使用自联接:

UPDATE 
    t1 
SET 
    t1.[timestamp_prev] = t2.[timestamp] 
FROM 
    [dbo].[Location Data] t1 
INNER JOIN 
    [dbo].[Location Data] t2 
    ON t1.[RowNumber] = t2.[RowNumber] + 1 AND 
     t1.[mmsi] = t2.[mmsi] 

如果您对连接列此查询可能之前完成指标你退休了。

0

像下面这样的内部连接可能会帮助您,而不是像在嵌套查询中那样遍历表的每一行中的所有行。

UPDATE oldTable 
SET oldTable.[timestamp_prev] = newTable.[timestamp] 
FROM [dbo].[Location Data] oldTable 
INNER JOIN [dbo].[Location Data] newTable 
    ON oldTable.[RowNumber] = newTable.[RowNumber] + 1 
       AND oldTable.[mmsi] = newTable.[mmsi] 
0

我会尝试这样的:

UPDATE T1 SET 
    [timestamp_prev] = T2.[timestamp] 
FROM [dbo].[Location Data] T1 
    INNER JOIN [dbo].[Location Data] T2 
     ON T1.RowNumber = T2.RowNumber + 1 
      AND T1.mmsi = T2.mmsi 
WHERE T1.[timestamp_prev] IS NULL; 

的加入应该是更有效的,只有尝试更新没有以前的时间戳记录。然后,您可以采取另一个步骤,将RowNumber,MMSI和Timestamp_Prev上的索引添加到表中,然后确保清理索引以最大限度地提高效率。

这样一个简单的指标应该是一个良好的开端:

CREATE NONCLUSTERED INDEX ix_Location_Data_MMSI_RowNumber_Timestamp_Prev 
    ON dbo.[Location Data] (mmsi, RowNumber, Timestamp_Prev) INCLUDE (Timestamp); 
2

首先,我会用lag()做到这一点:

with toupdate as (
     select ld.*, 
      lag(timestamp) over (partition by mmsi order by RowNumber) as prev_timestamp 
     from dbo.[Location Data] ld 
    ) 
update toupdate 
    set timestamp_prev = prev_timetamp; 

然后,我要指出,更新2亿条记录是要花费很长,很长很长的时间。我建议你用你想要的列生成一个新表,然后截断原始表并重新填充它。

+1

不错的** **滞后**。不知道这甚至存在! – Sam

+1

@Sam [LAG](https://msdn.microsoft.com/en-IN/library/hh231256.aspx)在'SQL SERVER 2012'中引入了 –

+2

@Prdp我猜Sam是'LAG'ging在后面:-) –