1. ホーム
  2. mongodb

[解決済み】フィルタリング用途のelasticsearch v.s. MongoDB【クローズド

2022-04-22 01:14:28

質問

この質問は、実験や実装の詳細に踏み込む前に、アーキテクチャの選択をすることに関するものです。スケーラビリティとパフォーマンスの観点から、特定の目的に対するelasticsearchとMongoDBの適合性についての質問です。

仮に、どちらもフィールドと値を持つデータオブジェクトを保存し、そのオブジェクトの本体をクエリすることができるとします。ですから、おそらくアドホックに選択されたフィールドに従ってオブジェクトのサブセットをフィルタリングすることは、どちらにも適していることでしょう。

私のアプリケーションは、条件に従ってオブジェクトを選択することを中心に展開されます。 つまり、クエリのフィルタリング基準は、通常1~5フィールド、場合によってはそれ以上のフィールドで構成されるでしょう。一方、フィルターとして選択されるフィールドは、より多くのフィールドのサブセットとなります。20ほどのフィールド名が存在し、各クエリはその20のフィールドのうちいくつかのフィールドでオブジェクトをフィルタリングする試みであるとします(全体のフィールド名は20より少なくても多くても構いませんが、この数字は個別のクエリでフィルタとして使われるフィールドとフィールドの比率を示すために使っただけです)。例えば、フィールドAを持ち、フィールドBがxとyの間であり、フィールドCがwに等しいオブジェクトをフィルタリングすることが可能です。

私のアプリケーションは、この種のフィルタリングを継続的に行うことになりますが、どのフィールドがフィルタリングに使用されるかという点では、どの瞬間でも何もないか、ほとんど一定ではありません。elasticsearchではインデックスを定義する必要があるかもしれませんが、インデックスがなくてもMongoDBの速度に匹敵するのかもしれません。

オブジェクトは挿入された後、ほとんど変更されることはないでしょう。古いオブジェクトは削除する必要があるかもしれませんが、どちらのデータストアも、内部またはアプリケーションが作成したクエリによって、期限切れの削除をサポートしていると仮定したいと思います。(あまり頻繁ではありませんが、特定のクエリに適合するオブジェクトも同様に削除される必要があるでしょう)。

どうでしょうか? また、この点について実験されましたか?

私は、この種のタスクに対する、2つのデータストアのそれぞれのパフォーマンスとスケーラビリティに興味があるのです。これはアーキテクチャ設計の質問のようなもので、十分に考え抜かれた提案のデモンストレーションとして、ストア固有のオプションや、うまくアーキテクチャされるべきクエリの基礎の詳細が歓迎されます。

ありがとうございます。

解決方法は?

まず最初に、ここで重要な区別をする必要があります。MongoDBは汎用データベース、ElasticsearchはLuceneに裏打ちされた分散型テキスト検索エンジンです。Elasticsearchを汎用データベースとして使うという話はよく聞きますが、これは本来の設計とは異なるものです。しかし、現状では、この2つは全く異なる陣営のものです。

私の会社では、MongoDBとElasticsearchの両方を使っています。MongoDBにデータを保存し、Elasticsearchはその全文検索機能のみを使用しています。クエリーが必要なMongoのデータフィールドのサブセットだけをElasticsearchに送っています。私たちの場合、Mongoのデータは常に変化しています。1つのレコード、またはレコードのフィールドのサブセットが1日に何度も更新され、そのレコードの再インデックス化がElasticに要求されることがある、という点で皆さんとは異なります。そのため、elasticを唯一のデータストアとして使用することは、私たちにとって良い選択肢ではありません。なぜなら、選択したフィールドを更新することができず、ドキュメント全体のインデックスを再作成する必要があるからです。これはelasticの制限ではなく、elasticの基盤となっている検索エンジンであるLuceneの仕組みです。あなたの場合、一度保存されたレコードは変更されないので、そのような選択をする必要はありません。とはいえ、もしデータの安全性が心配なら、Elasticsearchをデータの唯一の保存メカニズムとして使うことはよく考えなければなりません。いずれはそうなるかもしれませんが、まだそこまでのレベルに達しているとは思えません。

Elastic/LuceneはMongoのクエリ速度に匹敵するだけでなく、フィルタリングに使用するフィールドが一定でない場合、特にデータセットが大きくなると桁違いに速くなる可能性があります。この違いは、基本的なクエリの実装にあります。

  • Elastic/Luceneでは ベクトル空間モデル 転置インデックス に対して 情報検索 これは、クエリに対するレコードの類似性を比較する非常に効率的な方法である。Elastic/Luceneにクエリを送ると、Elastic/Luceneはすでに答えを知っており、クエリ用語と一致する可能性の高い結果をランキングするのが主な仕事です。これは重要なポイントです。検索エンジンはデータベースとは異なり、正確な検索結果を保証することはできませんので、お客様のクエリにどれだけ近いかを基準に結果をランク付けします。検索エンジンは、データベースとは異なり、正確な検索結果を保証することはできません。
  • Mongoのアプローチは、より汎用的なデータストアで、JSONドキュメント同士を比較するものです。しかし、実行するクエリに合わせてインデックスを慎重に作成する必要があります。具体的には、クエリの対象となるフィールドが複数ある場合、そのフィールドに対応するインデックスを慎重に作成する必要があります。 複合キー で、クエリーの対象となるデータセットをできるだけ小さくします。例えば、最初のキーでデータセットの大部分を絞り込み、 2 番目のキーで残ったものをさらに絞り込み、といった具合です。もし、クエリが定義されたインデックスにあるキーやキーの順番と一致しない場合は、パフォーマンスが大きく低下します。一方、Mongoは真のデータベースなので、正確さを求めるのであれば、Mongoが出す答えは的確なものになります。

古いレコードを失効させるために、ElasticはTTL機能を内蔵しています。Mongoはバージョン2.2から導入されたばかりだと思います。

予想されるデータサイズ、トランザクション、精度、フィルターの種類など、その他の要件が分からないので、具体的な推奨事項はありません。しかし、ここにある情報は、あなたが始めるのに十分なものであることを願っています。