MachbaseとMongoDB:時系列センサーデータのアーキテクチャと性能比較

概要
本稿では、MachbaseとMongoDBのアーキテクチャの違いを確認し、時系列センサーデータの処理性能を比較します。センサーデータ処理システムを開発するとき、使い慣れたDBMSを選びたくなるものです。しかし、データの特性を考慮せずに選ぶと、予想していなかった処理上の課題に直面することがあります。
Machbaseについて
Machbaseは、時系列センサーデータの高速な取り込み、検索、集計を目的として開発されたDBMSです。Raspberry Piなどのエッジ機器、一般的な単一サーバー、複数サーバーのクラスターに対応し、センサーデータとマシンログに特化した機能とアーキテクチャを備えています。詳しい構造は後ほど説明します。
MongoDBについて
MongoDBはドキュメント指向のデータベースエンジンです。柔軟な構造のデータをJSONに近い形で保存・取得できるため、Web分野で便利に利用されています。半導体製造では設備からXML形式のデータが生成されることもあり、柔軟なデータ表現を扱いやすいという理由で採用される場合があります。本稿では、そのような汎用的なドキュメントモデルと、時系列センサーデータ専用の設計を比較します。
時系列センサーデータの特徴とアーキテクチャ
時系列センサーデータは、1件あたりのサイズは小さく、通常は更新せず、時間とともに追加し続けるデータです。センサーごとに測定値が時刻順に並びます。設置するセンサーの増加と収集周期の短縮により、単位時間に発生するデータ量は急増します。
さらに長期保存も求められるため、大量のデータを格納・処理するシステムの構築は容易ではありません。検索では時刻とセンサーIDを組み合わせることが多く、リアルタイム処理には高い取り込み性能が必要です。
以下で、それぞれの設計を詳しく比較します。
固定スキーマと柔軟なスキーマ
Machbaseでは、リレーショナルモデルに基づいてSQL DDLでスキーマを定義します。MongoDBでは、コレクション内のドキュメントが同一の固定スキーマを持つ必要はありません。
Webサイトのユーザー設定をJSONで表現して処理するのは一般的な方法です。その構造を保ったままMongoDBへ格納し、ユーザーIDで素早く取得できる点は便利です。MongoDBはデータをBSONというバイナリー形式で保存します。次の例を見てください。

出典:Wikipedia
BSONはバイナリー形式でデータを表現しますが、各属性について型や名前などの情報を保持します。柔軟なスキーマでは、あるドキュメントに存在するフィールドが別のドキュメントには存在しない場合があり、型や長さも変わり得ます。属性bを読み出すには、ドキュメント内でそのフィールドの有無と型を確認する処理が必要になります。
一方、固定スキーマでは列名と型が共通です。格納形式を事前に把握できるため、必要な列の位置を特定しやすくなります。その代わり、任意の構造を自由に混在させる用途には制約があります。
では、リアルタイムのセンサーデータはどうでしょうか。あらかじめ決めた列を持つ構造化データであれば、固定スキーマで表現・処理することは自然です。
もちろんMongoDBでも扱えます。ここで、構造化データと柔軟な構造のデータを簡単に比較してみましょう。

非構造化データや構造が不定なデータを固定スキーマに変換する場合、ERモデルなどでデータモデルを設計し、適切なテーブルへ変換して格納する必要があります。元の構造をそのまま表現しにくい場合もあります。
MongoDBのように柔軟なドキュメント構造を維持できる仕組みは便利です。一方、検索・集計時にフィールドを解釈して値を取り出す処理は、ワークロードによっては負担になります。分散処理で補う方法もありますが、サーバー台数が増えればコストも増加します。
構造化データでは、スキーマを利用して必要な値へ効率よくアクセスでき、大量処理の性能向上につながります。本稿で扱うような定型的なセンサーデータでは、この特性を生かした設計が有効です。
SQLとMongoDBのクエリ
Machbaseは問い合わせ言語としてSQLを提供し、MongoDBは独自のクエリ方式を提供します。ここでは、その記述方法の違いを見ていきます。
構造化データへの問い合わせでは、長い歴史があり広く使われているSQLが一般的です。NoSQL製品も普及していますが、処理方式は製品ごとに異なるため、本稿ではMongoDBのクエリに絞って説明します。
MongoDBでは、Webサービスなどが扱うJSONに近いドキュメントをコレクションにまとめます。リレーショナルモデルのテーブルに相当する管理単位です。キーで特定のドキュメントを取得する操作は簡潔で、データの追加とキーによる取得を中心とする用途に適しています。

findメソッドに条件を指定すれば、検索条件を追加できます。オブジェクトを扱うプログラムから自然に記述できる方式です。
時系列データでは、特定のセンサーIDについて、ある期間の測定値を取得する処理がよく使われます。MongoDBでも実行できますが、2つの記述を比較すると違いが見えてきます。
Machbaseのクエリ(SQL)

特定のセンサーIDを持つ1日分のデータを取得する例です。SQLでは、取得したい条件を宣言的に記述できます。
MongoDBのクエリ

同じ条件をMongoDBで表すと、上のSQLより記述量が増えます。
集計
大量のセンサーデータは、時間単位で集計して可視化することがよくあります。Machbaseには時間別の集計値を自動生成するRollup機能があり、後述する事前集計を使って必要な統計値をSQLから取得できます。

この例ではROLLUPヒントを指定し、問い合わせのたびに元データを集計する代わりに、事前計算された集計値を参照しています。
MongoDBでも同様の集計を実行できますが、この例ではクエリの記述がさらに長くなります。

使いやすさの感じ方は人によりますが、集計や複雑な条件を表すと、MongoDBの記述量が増える場合があります。
時系列センサーデータでは時間別集計を頻繁に使うため、条件が複雑になるにつれて、クエリの作成・保守に必要な作業も考慮する必要があります。
センサーデータ専用インデックスとB+Tree
RDBMSでもよく使われるB+Treeインデックスは、次のような構造です。

キーはリーフノードに格納され、リーフ同士のリンクをたどって順番にアクセスできます。
リーフが満杯になるとノード分割などで構造を調整します。キーの分布が偏っていても、木の高さが一方に偏らないように設計されています。
この構造は、ディスクベースのRDBMSで一般的な検索に有効です。では、時刻とセンサーIDを同時に考慮する時系列検索では、どのようなアクセスが発生するでしょうか。
Machbaseのセンサーデータインデックスは、時刻とセンサーIDに基づく検索に特化した構造を持ちます。
多くのセンサーデータ検索は時間範囲とセンサーIDを指定するため、その条件に合わせてインデックスを最適化しています。以下で両者の特徴を比較します。

B+Treeでは、大量のデータを取り込む際にインデックス更新の負荷が増える場合があります。
高速な連続取り込みでは、ノード分割などの構造変更操作(SMO)が発生します。実装によっては、読み書きの整合性を保つために木の一部をロックし、ほかのセッションの処理を待たせることがあります。
B+Treeは、一般的な検索や部分更新を含む幅広い用途に適しています。一方、高速で大量のセンサーデータが流入する環境では、インデックス更新のコストが性能上の課題になる場合があります。
一般的なセカンダリーインデックスには、キーとレコード識別子が格納されます。キーを検索した後、識別子を使ってデータ本体を取得するため、配置によってはランダム読み取りが発生します。キー順にデータ本体を配置するクラスター化方式もありますが、ここでは図に示す非クラスター化のアクセス構造を比較します。
次の図で時刻だけにインデックスを作った場合、指定期間には多数のセンサーのデータが混在します。赤い四角が対象センサーのデータだとすると、それらは連続していないため、リーフを走査し、各レコード識別子からデータを取得する処理が必要です。センサー数が多く、収集周期が短いほど、走査とランダム読み取りの量が増えます。実際の性能は、複合インデックスなどの設計によっても変わります。

Machbaseでは、時刻で分割したインデックスファイルを作成します。各ファイルはセンサーID、時刻、値を並べて保存し、パーティションの最小・最大時刻をメモリーに保持します。検索期間と重ならないパーティションは、検索対象から除外できます。
時間分割によって検索範囲を絞るとともに、新しいデータの反映を主に書き込み中のパーティションへ限定することで、過去のインデックスへの変更を抑えます。この設計により、取り込み、インデックス作成、検索を並行して処理しやすくしています。
対象パーティション内では、同じセンサーIDのデータが時刻順にまとまっているため、時間条件を効率よく絞り込めます。必要なセンサー値も同じインデックスに含まれるので、短い範囲の順次読み取りで取得できます。
この比較から、Machbaseの専用インデックスが、ここで挙げた時系列処理の課題を軽減するために設計されていることが分かります。
取り込みと単純検索の性能比較
固定スキーマとセンサー専用インデックスを組み合わせることで、対象の時系列ワークロードではMachbaseの性能上の利点が期待できます。
次の条件でテストしました。
事前に作成した107GBのCSVを、各製品の専用ツール(csvloader、mongoimport)で取り込み
タグ名とタイムスタンプにインデックスを作成
4コアXeon CPU、32GB RAM、SSD

このテストでは、MongoDBのほうがリソース使用量が多く、Machbaseは8倍以上の速度でデータを取り込みました。
続いて、単純検索の性能を比較しました。
単純検索の性能
特定タグの1日分のデータをすべて取得するクエリです。


2つのクエリの測定結果は以下のとおりです。

この条件では200倍以上の性能差があり、Machbaseのセンサーデータ向け設計の効果が表れています。
自動Rollupと問い合わせ時の集計
大量のセンサーデータから、例えば10年分の傾向を表示するには、膨大な読み取りと集計が必要になります。
可視化アプリでは、ズームや時間範囲の移動にすぐ応答する必要があります。元データを高速に検索できても、数億件を表示用の時間単位にまとめる処理が重ければ、対話的な操作は難しくなります。
時間単位の統計値を事前に作成しておけば、集計クエリを高速化できます。Machbaseはセンサーデータの集計値を自動生成・保存し、クエリから取得する機能を提供します。
次に、同じ集計結果を求めるクエリを比較します。MachbaseはSQLと事前集計を使い、MongoDBは以下の集計クエリを使っています。この比較には、事前計算を利用するかどうかの違いも含まれます。
以下は、特定センサーについて1日分の毎分最大値を取得するクエリです。Machbaseではヒントによって、あらかじめ生成された集計値を参照します。

MongoDBでは、次のJSON形式の集計処理を実行します。

測定結果は以下のとおりです。

このテストでは、約400倍の性能差が確認されました。
まとめ
MachbaseとMongoDBのアーキテクチャを比較し、時系列センサーデータ処理での性能差を確認しました。MongoDBの柔軟なドキュメントモデルはWebアプリなどで便利ですが、本稿の構成とワークロードでは、センサーデータに特化したMachbaseが高い性能を示しました。結果は使用した構成とテスト条件に依存し、現在の各製品が持つすべての機能を評価したものではありません。
スマートファクトリーやスマートシティでは大量のセンサーデータが発生し、その処理に多くの課題があります。Machbaseが解決策の一つとなることを願い、本稿をまとめました。
機会があれば、ほかのデータベースとの比較も紹介したいと思います。
お読みいただき、ありがとうございました。
著者:Machbase CTO シム・グァンフン


