如何在数百万行的桌子上有效地获得最新的Instert时间戳

时间:2018-03-10 13:38:15

标签: sql-server sql-server-2012 triggers sql-server-2016 sql-view

我对SQL很新,对表设计/查询效率有疑问。

我有两个表,表A包含客户端列表,表B包含客户端ID以及上次从客户端收到消息的时间。

客户数量正在增长,并且数以千计,每个客户端每分钟至少发送一次消息,有时甚至更多,有时甚至更少,但平均而言就是这样。

表B增长相当快。

问题是:我希望能够提取所有客户的清单以及他们上次见到的日期和时间。

问题是随着表的增长,查询执行时间越来越大,需要扫描表A和B中的所有行。

我已经向表B引入了一个新列,它只是一个日期类型列,并在其上创建了非聚集的,非唯一的索引,但它似乎没有太大的区别。

查询是:

SELECT [TableA].[Client_ID] ISNULL(R.Most_Recent_TimeStamp, '2000-01-01') AS Most_Recent_Comms
FROM [TableA]
LEFT JOIN (SELECT [TableB].[Client_ID], MAX([TableB].[Time_Stamp]) AS Most_Recent_TimeStamp FROM [TableB] WITH(NOLOCK) GROUP BY [TableB].[Client_ID]) AS R ON [TableA].[Client_ID] = R.Client_ID

执行时间是几十秒。当我把(NOLOCK)声明包括在内时,情况有所改善。你可以想象随着时间的推移和TableB的增长,执行时间将会越来越长。

我不认为这是正确的方法。

我相信有更好的方法。如何创建一个视图或另一个表并编写一个触发器,每次将一行插入TableB时,它将更新新表。新表将始终保持最新,并且可以调用简单的SELECT查询。

我真的希望有人可以提供一些宝贵的意见。

非常感谢!

1 个答案:

答案 0 :(得分:0)

我会建议以下之一:

SELECT b.ClientId, MAX(b.TimeStamp)
FROM TableB b
GROUP BY b.ClientId;

这假设所有客户都在TableB。如果不是:

SELECT a.ClientId, b.TimeStamp
FROM TableA OUTER APPLY
     (SELECT b.*
      FROM TableB b
      WHERE b.Client_Id = a.Client_Id
      ORDER BY b.TimeStamp DESC
     ) b;

对于这两个查询,您需要TableB(ClientId, TimeStamp)上的索引。