我对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查询。
我真的希望有人可以提供一些宝贵的意见。
非常感谢!
答案 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)
上的索引。