8

大きなデータベース(数千万行)のフロントエンドを構築しています。データはさまざまな企業の負荷の水使用量であり、表は次のようになります。

id | company_id | datetime            | reading | used | cost
=============================================================
1  | 1          | 2012-01-01 00:00:00 | 5000    | 5    | 0.50
2  | 1          | 2012-01-01 00:01:00 | 5015    | 15   | 1.50
....

フロントエンドでは、ユーザーはデータの表示方法を選択できます。たとえば、6時間ごとの増分、1日ごとの増分、1か月ごとなどです。これをすばやく行うための最良の方法は何でしょうか。データが大きく変化し、1セットのデータが表示される回数を考えると、クエリデータをmemcahceなどにキャッシュすることはほとんど無意味であり、変数が多すぎるため、事前にデータを作成する方法はありません。

ある種の集約集計テーブルを使用すると、、、などのテーブルがまったく同じ構造で、すでに集計されているreadings場合に機能すると考えました。readings_6hreadings_1d

これが実行可能なソリューションである場合、集計テーブルを最新かつ正確に保つための最良の方法は何ですか。メーターから入ってくるデータに加えて、テーブルは読み取り専用です。ユーザーはそれを更新したり書き込んだりする必要はありません。

考えられる解決策は次のとおりです。

1)その場でグループ/集計関数を使用してクエリを実行することに固執する

2)基本的な選択と保存を行う

SELECT `company_id`, CONCAT_WS(' ', date(`datetime`), '23:59:59') AS datetime, 
MAX(`reading`) AS reading, SUM(`used`) AS used, SUM(`cost`) AS cost 
FROM `readings`
WHERE `datetime` > '$lastUpdateDateTime'
GROUP BY `company_id`

3)重複キーの更新(ここで集計がどのように行われるかわからない。また、データが2回カウントされたり、行が欠落したりしないように正確であることを確認します。

INSERT INTO `readings_6h` ... 
SELECT FROM `readings` .... 
ON DUPLICATE KEY UPDATE .. calculate...

4)他のアイデア/推奨事項?

私は現在、オプション2を実行しています。これは、4つのテーブル(_6h、_1d、_7d、_1m、_1y)で+-10万行を+-30k行に集約するのに約15分かかります。

TL;DR効果的にキャッシュできない多数のレポートの集計データを表示/保存するための最良の方法は何ですか。

4

1 に答える 1

11

この機能は、残念ながらMySQLにはないマテリアライズドビューと呼ばれる機能によって最適に提供されます。PostgreSQLなどの別のデータベースシステムへの移行を検討できます。

ストアドプロシージャ、トリガー、およびイベントを使用して、MySQLでマテリアライズドビューをエミュレートする方法があります。集計データを更新するストアドプロシージャを作成します。挿入ごとに集計データを更新する必要がある場合は、プロシージャを呼び出すトリガーを定義できます。データを数時間ごとに更新する必要がある場合は、MySQLスケジューライベントまたはcronジョブを定義して更新できます。

オプション3と同様に、入力データの日付に依存しない組み合わせアプローチがあります。いくつかの新しいデータが到着するのが遅すぎて、それが集計に含まれない場合にどうなるか想像してみてください。(この問題は発生しない可能性がありますが、わかりません。)新しいデータを「バックログ」に挿入するトリガーを定義し、プロシージャにバックログからのみ集計テーブルを更新させることができます。

これらのメソッドはすべて、この記事で詳細に説明されています:http: //www.fromdual.com/mysql-materialized-views

于 2012-07-26T19:04:53.197 に答える