【问题标题】:How to efficiently get latest Insert Time Stamp on a table with millions of rows如何在具有数百万行的表上有效地获取最新的插入时间戳
【发布时间】:2018-08-18 23:10:52
【问题描述】:

我对 SQL 中的表设计/查询效率有疑问。

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

客户端的数量正在增长,在数十个 1000 中,每个客户端至少每分钟发送一次消息,有时更多,有时更少,但平均而言就是这样。

表 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】:

    我会建议以下之一:

    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) 上的索引。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-22
      • 1970-01-01
      • 2011-01-04
      • 1970-01-01
      • 1970-01-01
      • 2013-04-27
      • 2013-01-17
      • 1970-01-01
      相关资源
      最近更新 更多