我根本不是SQL大师,但我有一个在小型FreeRadius服务器上自动使用的SQL查询。现在我们想在更大的服务器上使用它,但我注意到查询需要很长时间,并且使用CPU 100%大约两分钟......
有没有人知道如何优化查询?目标是查找用户是否有多个活动登录,并获取最早的登录信息。
我们还可以接受更多结果,并在PHP中进行排序,以减少radius-database上的负载。
以下是我们今天使用的查询:
SELECT username, acctstarttime, acctsessionid, nasipaddress, framedipaddress
FROM radacct
WHERE username IN (
SELECT username
FROM radacct
WHERE acctstoptime IS NULL
GROUP BY username
HAVING COUNT(username) > 1
)
AND acctstoptime IS NULL
GROUP BY username
ORDER BY username, acctstarttime ASC
此致
金
答案 0 :(得分:0)
删除子查询
SELECT username, acctstarttime, acctsessionid, nasipaddress, framedipaddress
FROM radacct
WHERE acctstoptime IS NULL
GROUP BY username
ORDER BY username, acctstarttime ASC
HAVING COUNT(username) > 1
或从外部查询中移除group by
(如果您希望获得包含重复username
的所有行
答案 1 :(得分:0)
我认为我们可以在整个radacct
表上进行一次传递:
SELECT username, MIN(acctstarttime) AS min_start_time
FROM radacct
WHERE acctstoptime IS NULL
GROUP BY username
HAVING COUNT(*) >= 2
LIMIT 0, 30;
这将仅返回具有两个或更多活动帐户的用户。它还会为每个用户返回最新的acctstarttime
值。
答案 2 :(得分:0)
查询响应是100%正确的,您应该能够通过一次传递完成此操作。然而2分钟是疯了!我也怀疑单次通过这不是你想要的那么快。 我们有一个状态页面,可以显示所有在任何特定时刻都在线的用户,因为支持原因听起来这与您尝试的相似。
首先确保你有acctstoptime的索引。 我还怀疑你在MYSQL配置中有一些不好的配置来处理这个庞大的表。 我还强烈建议做一个存档数据库,并将所有活动会话保存在一个小数据库中,这将有助于大量更新和插入免费的半径记帐。
我们每天有超过100,000名活跃用户,临时更新为300秒,每年产生大约30亿行。我们的每一个查询都不到1秒。我很乐意帮助您优化您的自由半径。