在从日志条目创建的会话表中查找并发用户

Posted

技术标签:

【中文标题】在从日志条目创建的会话表中查找并发用户【英文标题】:Finding concurrent users in a sessions table created from log entries 【发布时间】:2013-10-27 13:05:54 【问题描述】:

我们正在探索使用 Bigquery 来存储和分析数以百万计的代表用户会话的日志条目。源原始日志条目包含“连接”日志类型和“断开”日志类型。

我们可以选择在将日志提取到 bigquery 之前对其进行处理,以便每个会话有一个条目,其中包含会话开始 TIMESTAMP 和“持续时间”值,或者单独插入每个日志条目并计算会话时间分析阶段。假设我们的表模式是这样的:

sessionStartTime: TIMESTAMP,
clientId: STRING,
duration: INTEGER

或(在我们为每个会话存储两个日志条目的情况下:一个连接和一个断开连接):

time: TIMESTAMP,
type: INTEGER, //enum, 0 for connect, 1 for disconnect
clientId: STRING

我们的问题是我们找不到使用 bigquery 获取并发用户的方法:理想情况下,我们可以编写一个查询,通过时间戳“桶”(假设每分钟)对会话表进行分区,并执行一个查询,该查询将给出我们在特定时间范围内每分钟的并发数。

考虑与日志条目相关的并发的简单方法是,在任何时刻,它们都是使用函数 f(t) = x0 + connected(t) - disconnects(t) 计算的,其中 x0 是初始并发用户计数(在时间 t0),并且 t 是“时间戳”桶(在本例中以分钟为单位)。

有人可以推荐一种方法吗?

谢谢!

【问题讨论】:

你能分享一个带有样本数据的公共数据集吗? 给你:imgdge:sopub.views 和 imgdge:sopub.sessions。有几点需要注意:1)我们需要将会话表与视图表连接起来,以便能够应用特定于内容的过滤器(例如,一个特定内容的最大并发会话数)。 2)我们无法控制“视图”数据何时进入以及“会话”数据何时进入,这就是为什么我们不能对其进行非规范化并且不能将我们需要的所有信息直接放在一张表中。 3) 视图表可能有重复。 【参考方案1】:

感谢您提供示例数据! (可在https://bigquery.cloud.google.com/table/imgdge:sopub.sessions 获得)

我会接受您的提议“我们可以选择在将日志提取到 bigquery 之前对其进行处理,以便每个会话都有一个条目,其中包含会话开始 TIMESTAMP 和“持续时间”值 em>”。这一次,我将使用 BigQuery 进行处理,并将结果保留在我自己的表中:

SELECT u, start, MIN(end) end FROM (
SELECT a.f0_ u, a.time start, b.time end
FROM [imgdge:sopub.sessions] a
JOIN EACH [imgdge:sopub.sessions] b
ON a.f0_ = b.f0_
WHERE a.type = 'connect'
AND b.type='disconnect'
AND a.time < b.time
)
GROUP BY 1, 2

这给了我 819,321 行。对于 BigQuery 来说不是一个很大的数字,但由于我们要组合它,它可能会爆炸。我们将限制计算并发会话的日期范围以保持正常。我会将此查询的结果保存到 [fh-bigquery:public_dump.imgdge_sopub_sessions_startend]。

一旦我有了所有会话的开始和结束时间,我就可以找到每个有趣的瞬间有多少并发会话。你说的分分钟?

所有有趣的时间都发生在:

SELECT SEC_TO_TIMESTAMP(FLOOR(TIMESTAMP_TO_SEC(time)/60)*60) time
FROM [imgdge:sopub.sessions]
GROUP BY 1

现在让我们将这个有趣的时间列表与我的新表中的所有会话结合起来。对于每一分钟,我们将计算在此时间之前开始并在此时间之后结束的所有会话:

SELECT time, COUNT(*) concurrent
FROM (
 SELECT u, start, end, 99 x
 FROM [fh-bigquery:public_dump.imgdge_sopub_sessions_startend]
 WHERE start < '2013-09-30 00:00:00'
) a
JOIN
(
 SELECT SEC_TO_TIMESTAMP(FLOOR(TIMESTAMP_TO_SEC(time)/60)*60) time, 99 x FROM [imgdge:sopub.sessions] GROUP BY 1) b
 ON a.x = b.x
 WHERE b.time < a.end
AND b.time >= a.start
GROUP BY 1

注意99 x。它可以是任何数字,我只是一直使用它来生成所有会话 * 的组合。这种组合游戏的会话太多,所以我用WHERE start &lt; '2013-09-30 00:00:00'限制它们。

这就是计算并发用户数的方法。

【讨论】:

【参考方案2】:

您能否代替 sessionStartTime 获取 sessionEndTime(或仅添加持续时间 + sessionStartTime)?如果你能做到这一点,就可以做出这样的事情。它并不完美,但它会给你一些相关的数据。

SELECT AVG(perMinute) as avgUsersMin FROM
(
    SELECT COUNT(distinct clientId, 1000000) as perMinute, YEAR(sessionEndTime) as y,
    MONTH(sessionEndTime) as m, DAY(sessionEndTime) as d, HOUR(sessionEndTime) as h, MINUTE(sessionEndTime) as mn FROM [MyProject:MyTable]
    WHERE sessionEndTime BETWEEN someDate AND someOtherDate
    GROUP BY y,m,d,h,mn
);

【讨论】:

我们需要每分钟并发计数,例如假设在上午 10 点到 11 点之间,每分钟有多少用户。这样我们就可以在某个时间点衡量内容的受欢迎程度 虽然这不会给你确切的信息,但它会给你在特定时间范围内每分钟的断开连接数。在任何 SQL 中都没有简单的方法来检查日期范围内的重叠数据。我认为您应该尝试像这样准备登录预处理。如果您只是通过每分钟登录一次,每分钟创建一些字典并检查该分钟有多少会话处于活动状态,那么这应该相当容易做到,如果正确完成,这应该是 O(n) 复杂度和更多记忆。

以上是关于在从日志条目创建的会话表中查找并发用户的主要内容,如果未能解决你的问题,请参考以下文章

oracle 如何限定用户并发会话数

connect-mongo 创建的条目未过期

connect-mongo 创建的条目未过期

MS Access:如何使用查询按月选择条目

Shiro 中的并发会话控制

TYPO3 QueryBuilder - 如何查找用户的最新记录?