web-dev-qa-db-ja.com

findの最速のSTLコンテナはどれですか?

序文として申し分なく、めったに変更されないデータの比較的小さなサブセットをキャッシュして、パフォーマンス上の理由でデータベースに頻繁にクエリを実行しないようにする必要があります。このデータは、他のテーブルのはるかに大きなデータセットによって頻繁に参照されるため、読み取り専用で頻繁に使用されます。

キャッシュされたオブジェクトを更新するためのスレッドセーフコールバックメカニズムと共にコミットの変更をリッスンしながら、基本的に問題の2つのテーブル全体をメモリに保存する機能を持つクラスを作成しました。

現在の実装には、各テーブルの要素に対して2つのstd::vectors 1つがあります。このクラスは、各ベクトル全体へのアクセスと、std::findstd::find_ifなどを介してテーブルデータの特定の要素を検索するための便利なメソッドの両方を提供します。

std::liststd::set、またはstd::map over std::vectorを使用して検索することをお勧めしますか?ほとんどの場合、新しい接続が作成されたときにデータベースから1回移入された後、これらのコンテナに要求されます。

また、VS2010またはBoostでサポートされているC++ 0x機能を使用することもできます。

31
AJG85

特定の値を検索するには、std::setstd::mapを使用するとO(log N)時間かかりますが、他の2つの値を検索するにはO(N) time; 、std::setまたはstd::mapの方がおそらく優れていますC++ 0xにアクセスできるため、平均して一定の時間がかかるstd::unordered_setまたはstd::unordered_mapを使用することもできます。

find_ifについては、任意の述語が必要であり、コンテナが任意に最適化できないため、それらの間にはほとんど違いがありません。

ただし、特定の述語でfind_ifを頻繁に呼び出す場合は、自分で最適化できます。カスタムコンパレータまたは特殊キーでstd::mapまたはstd::setを使用し、findを使用します代わりに。

53

std::lower_boundを使用して並べ替えられたベクトルは、頻繁に更新しない場合はstd::setと同じくらい高速です。両方ともO(log n)です。どちらが自分の状況に適しているかを確認することは両方とも試してみる価値があります。

21
Mark Ransom

(拡張)要件から複数のフィールドを検索する必要があるため、Boost.MultiIndexを指定します。

このBoostライブラリを使用すると、oneコンテナー(含まれる各要素の1つの例のみ)を構築し、任意の数のインデックスにインデックスを付けることができます。また、使用するインデックスを正確に指定できます。

使用するインデックスの種類を決定するには、広範なベンチマークが必要です。 500はエントリ数が比較的少ないため、一定の要因はうまく機能しません。さらに、シングルスレッドとマルチスレッドの使用には顕著な違いがあります(ほとんどのハッシュテーブル実装は、線形リハッシュを使用しないため、MT使用で崩壊する可能性があります。スレッドはテーブルを再ハッシュし、他のすべてをブロックします)。

パフォーマンスの違いが目立たないか、単に重要ではない場合、範囲要求(Abcで始まるすべての名前)に対応するために、ソートされたインデックス(可能であればスキップリストのような)をお勧めします。

3
Matthieu M.

試して。それは非常に簡単で、STLでコンテナはほとんど交換可能です。

2
Piotr

テーブル内の特定の1つの列のみを個別の値として検索する場合は、std::hashが最速です。

いくつかの異なる述語を使用して検索できるようにするには、何らかのインデックス構造が必要になります。現在のベクターベースのアプローチを、検索するフィールドごとに1つずつ、複数のハッシュテーブルまたはマップで拡張することで実装できます。値は、ベクターへのインデックス、またはベクター内の要素への直接ポインターです。

さらに進んで、7月に日付があるすべての機会など、範囲を検索できるようにするには、範囲を抽出できる順序付けられたデータ構造が必要です。

2
Anders Abel

Stlではありませんが、市販のc ++コンテナは、検索、削除、変更にO(1)が含まれ、挿入中にO(logn).

0
Jonathan Yue