如何查询MySQL应用的历史最大并发登录用户数及对应时间
问题分析与解决方案
你原查询的错误点
第一个查询逻辑偏差:
你的第一条SQL只是筛选出登录时间早于登出时间的用户,计算单个用户的登录时长,完全没涉及「同时在线用户数」的统计逻辑,自然得不到并发相关结果。第二个JOIN查询的错误:
- 存在字段名错误:
A.last_login_datetime是不存在的字段,表中实际字段为last_login; - 逻辑方向错误:该查询只是找出登录时段有重叠的用户对,无法统计某个时间点的总在线人数,也无法定位最大并发的数值和对应时间。
- 存在字段名错误:
正确实现方案
要统计历史最大并发登录数、对应时间及当时的在线用户,核心思路是:把「登录」和「登出」拆分为独立事件,通过计算事件序列的累计在线人数找到峰值,再反向匹配该时间点的在线用户。
针对MySQL 5.7的兼容版SQL(5.7不支持WITH子句)
-- 1. 先获取历史最大并发数 SET @max_users = ( SELECT MAX(concurrent_users) FROM ( SELECT SUM(delta) OVER (ORDER BY event_time) AS concurrent_users FROM ( -- 拆分登录(+1在线人数)、登出(-1在线人数)事件 SELECT last_login AS event_time, 1 AS delta FROM Users WHERE last_login < last_logout UNION ALL SELECT last_logout AS event_time, -1 AS delta FROM Users WHERE last_login < last_logout ) AS event_times ) AS running_counts ); -- 2. 查询最大并发数、对应时间及在线用户名 SELECT @max_users AS 最大并发登录数, rc.event_time AS 峰值时间, GROUP_CONCAT(u.username SEPARATOR ', ') AS 在线用户名 FROM ( SELECT event_time, SUM(delta) OVER (ORDER BY event_time) AS concurrent_users FROM ( SELECT last_login AS event_time, 1 AS delta FROM Users WHERE last_login < last_logout UNION ALL SELECT last_logout AS event_time, -1 AS delta FROM Users WHERE last_login < last_logout ) AS event_times ) AS rc JOIN Users u ON u.last_login <= rc.event_time AND u.last_logout >= rc.event_time WHERE rc.concurrent_users = @max_users GROUP BY rc.event_time ORDER BY rc.event_time;
逻辑说明
- 事件拆分:通过
UNION ALL把每个用户的last_login标记为「在线人数+1」事件,last_logout标记为「在线人数-1」事件; - 累计计算:用窗口函数
SUM(delta) OVER (ORDER BY event_time)按时间顺序累计在线人数,得到每个时间点的实时在线数; - 定位峰值:先找到最大的累计在线数,再反向匹配该时间点所有满足「登录时间≤峰值时间且登出时间≥峰值时间」的用户,即为当时的在线用户。
内容的提问来源于stack exchange,提问作者Arj
相关产品推荐
相关产品推荐

