1

5 秒ごとにデータベースにクエリを実行して、現在ソフトウェアをアクティブに使用しているユーザーを特定する SQL クエリがあります。アクティブなユーザーが過去 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;
4

6 に答える 6

2

これをより速く実行したい場合は、 にインデックスを作成user_sessions(last_access_ts, user_name)し、クエリで日付ロジックを実行します。

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

これには欠点があります。おそらく、last_access_tsフィールドを頻繁に更新しています。フィールドのインデックスも更新する必要があります。良い面としては、これはカバリング インデックスであるため、元のデータ ページに頼ることなく、インデックス自体でクエリを満たすことができます。

于 2013-08-28T13:41:52.057 に答える
0

次のクエリを使用して、データベースに比較させてください。

    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;

SQLフィドル

于 2013-08-28T13:43:40.197 に答える
0

私の理解が正しければ、user_sessionsテーブルには 500 エントリしかありません。この場合、私はインデックスを気にしません。捨てなさい。いずれにせよ、DB エンジンは、このようにレコード数が少ない場合、おそらくそれらを使用しません。レコードの更新ごとにインデックスを更新しないことによるパフォーマンスの向上は、おそらくクエリのオーバーヘッドよりも高くなる可能性があります。

DB の負荷が気になる場合は、アプリケーションで許可されている場合は、クエリ/更新の間隔を 1 分以上に延ばしてください。ただし、Gordon Linoff の回答により、最高のクエリ パフォーマンスが得られるはずです。

補足として(以前に噛まれたことがあるため):すべてのユーザーコールバックに同じ同期時間を使用しない場合、「アクティブユーザーロジック」には設計上の欠陥があります。

于 2013-08-28T14:14:52.353 に答える