如何在具有数百万行的表上有效地获取最新的插入时间戳记

问题描述 投票:0回答:1

我对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

执行时间以数十秒为单位。当我包含相当数量的WITH(NOLOCK)语句时,情况有所改善。您可以想象,随着时间的推移和TableB的增长,执行时间将会增长。

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

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

sql-server sql-server-2012 triggers sql-server-2016 sql-view
1个回答
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)上建立索引。

© www.soinside.com 2019 - 2024. All rights reserved.