【问题标题】:Concurrent User Dashboard并发用户仪表板
【发布时间】:2013-04-30 23:01:10
【问题描述】:

我有一个应用程序的用户访问日志表。以下是一些示例数据:

userid    |          login          | duration (seconds)
--------------------------------------------------------
1         | 2013-04-30 09:24:07.127 | 21456     
2         | 2013-04-29 09:22:05.023 | 26477     
1         | 2013-04-30 10:24:07.787 | 86543    
2         | 2013-04-30 12:55:55.846 | 32237    
1         | 2013-04-30 08:24:12.347 | 92231     

我的目标是从这些数据中获取一些指标。我需要捕获过去一周的最小、最大和平均并发登录用户。除非有人有更好的主意,否则我相信要获得有意义的并发连接平均值,我将需要选择一个间隔。如果我在那里错了,请纠正我。如果是这样,我认为我不应该有麻烦。它的最小值和最大值给我带来了问题。我正在尝试在 sql 中执行此操作,但无济于事。问题是试图弄清楚如何测量连接之间的重叠。我应该把它拿出来用python做吗?我会有 100,000+ 行,所以可能会有点麻烦,但我每天只需要生成一次报告,所以效率不是我最关心的问题。

对不起,我没有任何示例代码,我真的不知道如何从这里开始。感谢您的帮助。

【问题讨论】:

  • 如果您想在一段时间内这样做,那么this 可能会有所帮助。尽管您可以汇总所有时间的数据,但它在几年前的仪表板上真的有意义吗?
  • 我只需要捕获一周或更晚的数据。
  • 如果您尝试评估系统上的负载,我无法想象这些用户即使已登录也处于活动状态。
  • 他们在闲置两个小时后退出。但无论它们是否处于活动状态,这都是我的任务是拉动的指标。上面的数据是假数据,我知道持续时间很长,所以不要让你失望。还有更多的行。我只是为了让您了解数据的样子。

标签: python sql sql-server


【解决方案1】:

这里有一些应该有所帮助的东西。例如,您可能必须努力弄清楚如何处理周界限。

这个想法是将数据分解为登录和注销。注销发生在登录后的登录 + secs 秒,因此很容易计算。每次登录都会获得+1 的值(将并发用户计数加一)。每次注销都会获得 -1 的值。

这个版本的查询使用相关的子查询来计算并发用户的数量和下一个事件的时间。在 SQL Server 2012 中,这些可以替换为累积总和(sum() over (partition . . order by)lead()

最后一步是计算平均值。这需要考虑持续时间才能准确。但是,这不是 100% 准确的,因为它会在没有登录的情况下错过开头和结尾的句点。为此,您可能需要将值为 0 的虚假记录添加到事件 CTE:

with d as (
        select 1 as userid, CAST('2013-04-30 09:24:07.127' as datetime) as logint, 21456 as secs union all
        select 2, CAST('2013-04-29 09:22:05.023' as datetime), 26477 union all
        select 1 , CAST('2013-04-30 10:24:07.787' as datetime), 86543 union all
        select 2, CAST('2013-04-30 12:55:55.846' as datetime), 32237 union all
        select 1, CAST('2013-04-30 08:24:12.347' as datetime), 92231
     ),
     events as (
      select logint as thetime, 1 as loginp
      from d
      union all
      select DATEADD(second, secs, logint), -1
      from d
     ),
     t as (
      select e.*,
             (select SUM(loginp) from events e2 where e2.thetime <= e.thetime) as concurrents,
             (select top 1 thetime from events e2 where e2.thetime > e.thetime order by e2.thetime desc) as nexttime,
             DATEDIFF(second, thetime, (select top 1 thetime from events e2 where e2.thetime > e.thetime order by e2.thetime desc)) as dur
      from events e
     )
select SUM(concurrents*1.0*dur)/SUM(dur) as avg_concurrents,
       MIN(concurrents), MAX(concurrents)
from t

这假设没有重复的时间——您无法区分问题中的重复时间。如果您有一个 id,很容易将其合并以了解接下来会发生什么,而不是使用时间。

【讨论】:

  • 所以我有点难以理解其中的一些逻辑,但我很困惑你为什么要这样做 with d as(select...... 然后选择我的示例表中的每一行。我不知道表中的内容是什么,因此很难将这些值插入到查询中。而且,我的表有 100,000 多行。我不想选择并合并所有这些。这就是你建议的例子吗?
  • @Hoopdady - 调试或理解此类操作的一种方法是将最后一个 select 替换为显示中间结果的操作。 select * from d 将显示您的示例数据。 select * from events 显示它变成了登录 (+1) 和注销 (-1) 表。 select * from t 显示然后奇迹发生步骤的第一部分。
猜你喜欢
  • 2011-04-20
  • 2011-12-29
  • 2017-07-15
  • 1970-01-01
  • 1970-01-01
  • 2021-02-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-06
相关资源
最近更新 更多