Java 执行此SQL查询的更有效方法?时间比较查询?

Java 执行此SQL查询的更有效方法?时间比较查询?,java,mysql,sql,Java,Mysql,Sql,我有一个SQL查询,它每5秒查询一次数据库,以确定当前正在使用该软件的用户。活动用户已在过去10秒内ping服务器。(该表在用户活动时得到正确更新,并且在会话超时时有一个线程逐出条目,这一切都正常工作) 我想要的是一种更高效/更快的方法,因为它经常被调用,大约每5秒调用一次。此外,数据库中最多可能有500个用户。语言是Java,但问题确实涉及任何语言 List<String> r = new ArrayList<String>(); Calendar c = Calen

我有一个SQL查询,它每5秒查询一次数据库,以确定当前正在使用该软件的用户。活动用户已在过去10秒内ping服务器。(该表在用户活动时得到正确更新,并且在会话超时时有一个线程逐出条目,这一切都正常工作)

我想要的是一种更高效/更快的方法,因为它经常被调用,大约每5秒调用一次。此外,数据库中最多可能有500个用户。语言是Java,但问题确实涉及任何语言

List<String> r = new ArrayList<String>();
Calendar c =  Calendar.getInstance();
long threshold = c.get(Calendar.SECOND) + c.get(Calendar.MINUTE)*60 + c.get(Calendar.HOUR_OF_DAY)*60*60 - 10;

String tmpSql = "SELECT user_name, EXTRACT(HOUR FROM last_access_ts) as hour, EXTRACT(MINUTE FROM last_access_ts) as minute, EXTRACT(SECOND FROM last_access_ts) as second FROM user_sessions";
DBResult rs = DB.select(tmpSql);
for (int i=0; i<rs.size(); i++)
{
   Map<String, Object> result = rs.get(i);
   long hour = (Long)result.get("hour");
   long minute = (Long)result.get("minute");
   long second = (Long)result.get("second");
   if (hour*60*60 + minute*60 + second > threshold)
      r.add(result.get("user_name").toString());
}

return r;
List r=new ArrayList();
Calendar c=Calendar.getInstance();
长阈值=c.get(日历秒)+c.get(日历分钟)*60+c.get(日历小时/天)*60*60-10;
String tmpSql=“选择用户名,提取(上次访问的小时数)作为小时,提取(上次访问的分钟数)作为分钟,提取(上次访问的秒数)作为用户会话的秒数”;
DBResult rs=DB.select(tmpSql);
对于(int i=0;i阈值)
r、 添加(result.get(“user_name”).toString());
}
返回r;

在您的选择中尝试MySQL
TimeDiff
功能。这样,您可以只选择活动的结果,而不必进行任何其他计算


链接:

我将把逻辑从Java移到DB。这意味着您将
if
转换为
where
,只需选择有效结果的名称

从上次访问的用户会话中选择用户名?

在您的示例中,
c
表示当前时间。结果很可能是空的


因此,您的问题应该更多地是关于数据库上的日期-时间操作。

如果希望运行得更快,请在
用户会话(上次访问,用户名)
上创建索引,并在查询中执行日期逻辑:

select user_name
from user_sessions
where last_access_ts >= now() - 5/(24*60*60);

这确实有缺点。您可能经常更新
last\u access\t
字段。该字段上的索引也必须更新。从积极的一面来看,这是一个覆盖索引,因此索引本身可以满足查询,而无需求助于原始数据页。

只需使用此查询让数据库为您进行比较:

    SELECT 
      user_name
    FROM user_sessions
    where TIMESTAMPDIFF(SECOND, last_access_ts, current_timestamp) > 10
完整示例:

List<String> r = new ArrayList<String>();
Calendar c =  Calendar.getInstance();
long threshold = c.get(Calendar.SECOND) + c.get(Calendar.MINUTE)*60 + c.get(Calendar.HOUR_OF_DAY)*60*60 - 10;
// this will return all users that were inactive for longer than 10 seconds
String tmpSql = "SELECT 
      user_name
    FROM user_sessions
    where TIMESTAMPDIFF(SECOND, last_access_ts, current_timestamp) > 10";
DBResult rs = DB.select(tmpSql);
for (int i=0; i<rs.size(); i++)
{
   Map<String, Object> result = rs.get(i);
   r.add(result.get("user_name").toString());
}

return r;
List r=new ArrayList();
Calendar c=Calendar.getInstance();
长阈值=c.get(日历秒)+c.get(日历分钟)*60+c.get(日历小时/天)*60*60-10;
//这将返回所有处于非活动状态超过10秒的用户
String tmpSql=“选择
用户名
来自用户会话
其中TIMESTAMPDIFF(第二次,最后一次访问,当前时间戳)>10”;
DBResult rs=DB.select(tmpSql);

对于(inti=0;i来说,解决方案是使用where子句从代码中删除sql查询的逻辑,以便仅从该select中获取活动用户

使用sql内置函数可以更快地在代码中获得更少的记录和迭代

将此添加到sql查询以仅获取活动用户:

Where TIMESTAMPDIFF(SECOND, last_access_ts, current_timestamp) > 10

这将为您获取日期为10秒之前或更早的所有记录。

如果我没有弄错,那么您的
user\u sessions
表中只有500个条目。在这种情况下,我甚至不关心索引。扔掉它们。对于如此低的记录计数,DB引擎可能无论如何都不会使用它们。由于没有更新,性能会有所提高每次记录更新的索引日期可能会高于查询开销

如果您关心数据库压力,那么如果您的应用程序允许,请将查询/更新间隔延长到1分钟或更长时间。Gordon Linoff的回答应该会为您提供最佳的查询性能


作为一个补充说明(因为它之前已经咬过我):如果你没有对所有用户回调使用相同的同步时间,那么你的“活动用户逻辑”在设计上是有缺陷的。

DateDiff只在天/月/年工作,这需要小时/分钟/秒来代替TimeDiff函数。这个链接有一个例子:或