大量のデータを集計するには・・

         

データ分析は可能な限りリアルタイムに集計し、分析できることが好ましい!

可能か???

例えば一般的なRDBMSで10,000件のデータにいくつかのクエリで集計を行うとする。

おそらく、複雑な計算をするようなものでなければ一瞬で終わると思う。

ほぼリアルタイムと言える。

では、10,000件のデータが100,000件になったとする。

もしかしたら10倍かかるかもしれない、でも元々0.1秒で終わっていたものとすると
まあ1秒で終わる。問題無し。

では、100倍、1000倍とデータ件数がかさんできたとしたら・・・。
それを1時間のうちに何度も実行するとすれば・・・。

もしかすると、集計周期を超えても実行が終わらないレベルの遅延になるかもしれない。

ではどう対応するか??

少し考えてみた。

※MySQLを利用していることを想定して記載します
※ここではデータ量はメモリに入りきらないサイズと仮定します

1. 読み込むデータ数を減らす

読み込むデータ数が増えれば増えるほど、それだけ時間がかかることになる。
そのため、効率的にデータを読み込むように対応する。

対応案① インデックス見直し
正しいインデックスとWHERE句の条件が指定されていること。
フルスキャンになっていない?

対応案② パーティショニング検討
インデックスを張る場合、データの更新時にI/Oが余分に発生することになる。
また、インデックスを作成することでディスク使用量も増加する。
ビックデータのようにデータ件数が多い場合は、ディスク容量も不足しがちになる。
そういう場合は、パーティショニングを作成することで、そのパーティション領域を
対象とする問い合わせは早くなる場合がある。ただし、パーティショニング+インデックス
が無い場合は、パーティション単位ではその中のフルスキャンが発生するため注意が必要。

対応案③ SQLチューニング
効率良く、結合や副問い合わせをしているか確認

対応案④ 要件にあったデータが格納されていることを確認する
集計に使う元データ中に要件としては必要の無いものが含まれていることがある。
それでは、読み込むデータ量も余分に増えてしまうし、キャッシュも無駄遣いしてしまう。

本当に必要なデータのみを残して、不必要なものは削除(そもそもテーブルに格納しない)
ような取捨選択をする。

対応案⑤ テーブル定義の見直し
データ量をなるべくすくなくするために、カラムの定義を見直す。
たとえば、bigintよりもint、intよりもtinyintなど数字の最大値に従い適切なデータ型を
使用する。
また、通常のRDBMSの場合、レコードはブロック単位で格納されている。
集計に使用しないデータが含まれているような場合は、使用頻度に応じて
垂直にパーティショニングをすることで、集計に使用する1レコードあたりのデータ量を削減する。
これにより、ブロックに含まれるデータ効率が向上し、その分I/O回数の削減にも
つながり、バッファプールなどのキャッシュも有効利用できる。

2. 一度問い合わせた結果は保持すること。時間を有効に使う。

データ件数が増えるということは、それらを単純に参照するだけでも時間を要する。
つまりは、一度参照したデータは本当に必要では無い場合には、二度と参照をしないように
検討する。

対応案① 副問い合わせの保存
似たタイプの集計を別々行う場合に、同じ副問い合わせを実行している場合がある。
特に、そこに時間を要する場合は、副問い合わせを実体化して保存しておき、使い回す。

対応案② 集計結果どおしの演算
毎時バッチ処理を走らせるような場合、前回の結果から、今回の結果までの差分を
足し合わせることで、前回の結果分は計算を行わなくて良くする。

たとえば、1日の中で時間ごとの集計を行う場合は、1時間前までの結果を残しておいて、今回の1時間分
の結果を足しあわせること。

3. 集計の並列化
集計は何もシリアルに1つ1つ実行する必要は無い。
昨今のサーバはCPU性能およびコア数も上がっているため、I/Oが許す限り
平行して処理が可能である。
そのため、独立して集計ができる処理に関しては並行して実行する。

サーバリソースはなるべく有効利用する。
空いているCPUがあれば使わないと損。

対応案①
Oracleなど商用のデータベースを使用している場合は、パラレルクエリのように
有償オプションではあるが、標準搭載された機能で並列化することが可能。
ただし、MySQLやPostgreSQLのようなオープンソースのRDBMSではそのような”標準”機能は
ないためアプリケーションプログラムで同様な処理を実装する必要がある。

4. 集計タイミングの見直し
1〜3の対応を行った場合でも、やむなく大量のデータを読み込むことになる場合もある。
その場合は、RDBMSの物理限界である可能性があるため、要件次第にはなるが
集計のタイミングを変えることも検討する。

対応案①
毎時集計の必要があるか?日時ではだめか?など

5. アーキテクチャ見直
あまりにも大量なデータになると、RDBMSでは対応できないことも発生する。

対応案①
Hadoopを使うなり、列指向データベースを使うなり、NoSQLを使うなりアーキテクチャを見直すことも必要となる。

ただし、アーキテクチャを見直すことで全てが解決するわけではなく、サーバ台数が増えたり
運用コストが増えたり、別のしわ寄せが発生する可能性が高いため、導入には十分な
検討が必要だと思われる。

以上、データ集計についてまとめてみましたが、誤りがご意見などありましたら、ご連絡ください。

コメントを残す