0

timestamps私は人と人のためのテーブルを持っていますstates

|:--------------------------------------------------------------:|
| user_id   |  state | start_time          | end_time            |
|:--------------------------------------------------------------:|
| 4711      |  1     | 2013-10-30 09:01:23 | 2013-10-30 17:12:03 |
| 4712      |  1     | 2013-10-30 07:01:23 | 2013-10-30 18:12:03 |
| 4713      |  1     | 2013-10-30 08:01:23 | 2013-10-30 16:12:03 |
| 4714      |  1     | 2013-10-30 09:01:24 | 2013-10-30 17:02:03 |

MAX(logged on) AND AVG(logged on)私の課題は、インターバルごとに同時に何人のユーザーがいるかを調べること です。1秒間に何人のユーザーが同時にログインしているかが分かると出てくると思います。

|:-------------------------------------:|
| timestamp  |  state | userid          |
|:-------------------------------------:|
| 1383123683 |  1     | 4711            |
| 1383123684 |  1     | 4711            |
| 1383123684 |  1     | 4712            |
| 1383123685 |  1     | 4711            |
| 1383123685 |  1     | 4712            |
| ...        | ...    | ...             |

ちなみに、1インターバルは15分です。

データが経由INSERT INTOするので、私の考えは、トリガーを作成し、開始と終了の間にstate_id.

最後に、秒単位でグループ化してカウントし、datasets1 秒間にいくつの行が存在するかを調べることができなければなりません。私はAVGまだ式を持っていません:-)。時間の問題ですよね。

しかし、私の計画が多くのパフォーマンスとスペースを必要とするのではないかと心配しているので、私のアイデアが良いものであったかどうかはわかりません.

より良いアイデアは、start-timeandだけを書くことですend-timeが、秒単位でグループ化する可能性を失います。

データベースに何千もの行がなくても、どうすればそれを管理できますか?

4

1 に答える 1

0

ここにいくつかの解決策があります。1 つを説明したいと思います。特定のニーズに合わせて使用​​/適応/拡張できることを願っています (注: 私は mysql 方言を使用しています。ms sql の場合、構文が少し異なる場合がありますが、アプローチが機能します):

1次のような構造の新しいテーブルを作成します。

create table changelog (
changetime datetime,
changevalue int,
totalsum int,
primary key (changetime)
);

2基本データの挿入:

insert into changelog
select changet, sum(cnts), 0
from
(
select start_time as changet, 1 as cnts from testlog
union all
select end_time as changet, -1 from testlog
) as q
group by changet;

3合計列を更新します。

update changelog as a set totalsum = ifnull((select sum(changevalue) from (select changet, sum(cnts) as changevalue, 0
from
(
select start_time as changet, 1 as cnts from testlog
union all
select end_time as changet, -1 from testlog
) as q
group by changet) as b where b.changet<=a.changetime),0);

注:ms sqlの場合with、構文を試すことができます。これらの挿入/更新を1つのクエリとして実行できます

4この後、(質問のデータに基づいて)次のようになります。

2013-10-30 07:01:23 1   1
2013-10-30 08:01:23 1   2
2013-10-30 09:01:23 1   3
2013-10-30 09:01:24 1   4
2013-10-30 16:12:03 -1  3
2013-10-30 17:02:03 -1  2
2013-10-30 17:12:03 -1  1
2013-10-30 18:12:03 -1  0

ご覧のとおり、max はすでにここにログインしていますが、ここに 1 つの問題があります。範囲のデータを選択する必要があると想像してください: 08:00-08:01、テーブルにデータがないため、次のようなクエリは機能しません:

SELECT max(totalsum)
FROM changelog
where changetime between cast(@startrange as datetime) and cast(@endrange as datetime)

ただし、次のように変更できます。

SELECT max(totalsum)
from
(
select max(totalsum) as totalsum FROM changelog
where changetime between cast(@startrange as datetime) and cast(@endrange as datetime)
union all
select totalsum from changelog where changetime=(select max(changetime) from changelog where changetime<cast(@startrange as datetime))
) as q;

つまり、基本的には、範囲に加えて、期間が始まる前に最後の行をフェッチして、範囲の開始時に何人のユーザーがいたかを調べる必要があります

5次に、平均を計算します。平均は、理解している内容に応じて、ちょっとトリッキーな関数です。異なる結果、1 秒あたりの平均ユーザー数、または平均ワークロードが存在する可能性があります。

違いは次のとおりです。

100 users logged in at 09:00
98 users logged out at 09:01
1 user logged out at 09:02
Selection range: 09:00 - 09:59 (inclusive)

1 分あたりの平均は、1 分間にログインしたすべてのユーザーの合計を 60 で割った値になります。

(100 + 2 + 1 + 57*1)/60 = 2.6(6) user per minute

ただし、平均ワークロードは (max(logged_users)+min(logged_users)) / 2 として計算できます。

(100 + 1)/2 = 50.5 users, this is average simultaneous users logged in system

別の平均は、SQL avg (sum(values)/count(values)) を使用して計算できます。

(100+98+1)/3 = 66.3(3) - another average workload in persons

最初の式は、同時に 2.65 ユーザーしかいないことを示していますが、2 番目の式は「神聖な #*&#@#@、同時に 50.5 ユーザーです」と示しています。

もう一つの例:

100 users logged in at 09:00
99 users logged out at 09:58
1 user logged out at 09:59
Selection range: 09:00 - 09:59 (inclusive)

最初の式は(100*58 + 2 + 1)/60 = 96.71(6)ユーザーを提供し、2 番目の式はユーザーを引き続き提供し50.5、3番目の式は引き続きユーザーを提供します66.3(3)

どの平均があなたに最も適していますか?

最初の平均を計算するstored procedureには、期間の分/秒ごとにデータを取得し、除算後に集計する必要があります。

2 番目のバリアントを計算するには: 選択min/maxして 2 で割るだけです

3 番目のバリアント: avgmax の代わりに使用

注 #1: もちろん、このすべてのアプローチは膨大なトラフィックで非常に遅いため、高速に取得できるデータを含む「事前計算済み」のテーブルをいくつか用意することをお勧めします (たとえば、次のように 1 時間ごとにデータを取得できますYYYY-MM-DD HH loggedInatStart, min, avg, median, max, loggedInatEnd) 。

注 #2:統計目的で中央平均の方が興味深い場合があります。それを取得するには、1 分ごとにログインしたユーザー数を計算し、個別の値を選択し、このリストから中央を選択します (私の例では、2 と 2 が得られます)。 2)、またはすべての値を選択し、中央の値を選択します(私の例では、1と99が得られます)

于 2013-10-31T00:38:10.357 に答える