1

いくつかのディメンションに分類された1時間ごとの統計データを含む大きなテーブルがあります。これで十分な大きさになり、クエリを高速化するためにデータの集計を開始する必要があります。テーブルは次のようになります。

customer INT
campaign INT
start_time TIMESTAMP
end_time TIMESTAMP
time_period ENUM(hour, day, week)
clicks INT

たとえば、キャンペーンがnullである行をテーブルに挿入でき、クリック数の値はその顧客と期間のすべてのクリック数の合計になると考えていました。同様に、期間を「日」に設定することもできます。これは、その日のすべての時間の合計になります。

これはかなり一般的なことだと確信しているので、MySqlでこれを達成するための最良の方法は何でしょうか?INSERT INTOをSELECTステートメントと組み合わせて(マテリアライズドビューのように)想定していますが、このテーブルには常に新しいデータが追加されているため、以前に計算した集計データの再計算を回避するにはどうすればよいですか?

4

2 に答える 2

1

私は似たようなことをしましたが、ここに私が対処した問題があります:

round(start_time/86400)*86400「group by」部分で使用して、同じ日のすべてのエントリの概要を取得できます。(週はほぼ同じ)

SQL は次のようになります。

insert into the_table 
( select 
   customer, 
   NULL, 
   round(start_time/86400)*86400, 
   round(start_time/86400)*86400 + 86400, 
   'day', 
   sum(clicks) 
  from the_table 
  where time_period = 'hour' and start_time between <A> and <B> 
  group by customer, round(start_time/86400)*86400 ) as tbl;

delete from the_table 
where  time_period = 'hour' and start_time between <A> and <B>;
  1. 同じテーブルからそれ自体に要約を挿入する場合は、temp を使用します (トランザクションごとに、テーブルからデータの一部を削除するのではなく、テーブルからコピーすることを意味します)。そのため、内部選択によって返されるデータのインデックスとサイズには十分注意する必要があります。
  2. 行の挿入と削除を頻繁に行うと、遅かれ早かれ断片化の問題が発生します。それはあなたを劇的に遅くします。解決策は、パーティショニングを使用して古いパーティションを時々削除することです。または、「テーブルの最適化」ステートメントを実行することもできますが、比較的長い時間 (数分かかる場合もあります) 作業を停止します。
  3. 重複データの混乱を避けるために、各時間集計期間 (hour_table、day_table、...) ごとにテーブルを複製することをお勧めします。
于 2013-04-21T12:15:06.353 に答える
0

テーブルを小さくしようとしている場合は、要約行を作成した後に詳細行を削除しますよね?トランザクションはあなたの友達です。1つを開始し、ロールアップを計算し、ロールアップを挿入し、詳細な行を削除して、トランザクションを終了します。

以前の期間に行を追加した場合(誰がそれを行うのですか??)、ロールアップを再度実行できます。これにより、以前のロールアップエントリと追加のデータが結合され、新しい、より強力なロールアップエントリになります。

于 2012-11-09T17:49:31.770 に答える