この例を示すために2つのデータベースを使用: CouchDB および Cassandra 。
CouchDBはドキュメントインデックスにB +ツリーを使用します( 巧妙な変更 を使用して追加専用環境で機能します)-より具体的には、ドキュメントが変更(挿入/更新/削除)されると、実行中のデータベースに追加されますファイルおよび完全なリーフ-> Nodeドキュメントの直後の更新されたリビジョンによって影響を受けるすべてのノードのB +ツリーからのパス.
これらの部分測定インデックスリビジョンは、変更の右側にインライン化されます。これにより、完全なインデックスは、ファイルの最後に追加された最新のインデックス変更と、データファイルでさらに関連があり、まだ追加されていない追加のピースの結合になります。まだ変更されていません。
B +ツリー の検索はO(logn)です。
Cassandraは、レコードキーをメモリ内のテーブルに並べ替えて保持し(この質問では配列と見なします)、それらを別々の(並べ替えられた) sorted-string tables として書き出します。
これらすべてのテーブルのコレクションは、(私が理解している限りでは)「インデックス」と考えることができます。
Cassandraは、時々 これらのソート済み文字列テーブルをコンパクト/結合 する必要があり、インデックスのより完全なファイル表現を作成します。
検索 ソートされた配列 はO(logn)です。
CouchDBでの部分的なB +ツリーチャンクの維持とCassandraでの部分的なソートされた文字列のインデックスのどちらかを維持することの間の同様のレベルの複雑さを仮定し、両方がO(logn)データベースインデックスをより適切に表すには、どの検索時間を使用すると思いますか。その理由は何ですか。
特に魅力的な実装の詳細が他にあるか、または両方がウォッシュであり、操作したい/より理にかなったデータ構造を選択した場合、私は特に興味があります開発者に。
考えてくれてありがとう。
BTreeインデックスをSSTableインデックスと比較するときは、書き込みの複雑さを考慮する必要があります。
コピーオンライトBTreeにランダムに書き込む場合、ランダムな読み取りが発生します(リーフノードとパスのコピーを行うため)。そのため、書き込みはディスク上でシーケンシャルになりますが、RAMよりも大きいデータセットの場合、これらのランダムな読み取りはすぐにボトルネックになります。 SSTableのようなインデックスの場合、書き込み時にそのような読み取りは行われません-順次書き込みのみになります。
また、最悪の場合、BTreeを更新するたびにlog_b N IOが発生する可能性があることも考慮する必要があります。つまり、すべてのキーに対して3つまたは4つのブロックを書き込むことになります。キーサイズがブロックサイズよりはるかに小さい場合、これは非常に高価です。 SSTableのようなインデックスの場合、各書き込みIOには可能な限り多くの新しいキーが含まれるため、IO各キーのコストは1/B..
実際には、これにより、SSTableに似たものがBTreesより数千倍(ランダムな書き込みの場合)速くなります。
実装の詳細を検討したところ、BTableのロック戦略が非常に複雑になったため、SSTableのようなインデックスを(ほとんど)ロックフリーで実装する方がはるかに簡単であることがわかりました。
読み取りコストも再検討する必要があります。 BTreeはランダムポイント読み取りのO(log_b N)ランダムIOよりも正しいですが、SSTableのようなインデックスは実際にはO(#sstables。log_b N)です。適切なマージスキームがない場合、#sstablesはNに比例します。これを回避するためのさまざまなトリックがあります(たとえば、ブルームフィルターを使用)。ただし、これらは小さなランダムな範囲のクエリには役立ちません。これは、Cassandraで見つけたものです。
これが、私たちの(GPL)ストレージエンジンであるCastleがわずかに異なる方法でマージし、書き込みパフォーマンス(O(log ^ 2 N/B))。実際には、書き込みについても、CassandraのSSTableインデックスよりも高速であることがわかります。
これについてもっと知りたいのであれば、私はそれがどのように機能するかについて話をしました:
各アプローチについても言及すべきいくつかの事柄:
O(logn)
と見なされます。ただし、単一のデータベース書き込みにより、ストレージシステムで複数の書き込みが発生する可能性があります。たとえば、ノードがいっぱいになった場合、ノードを分割する必要があります。つまり、2つの新しいノードに2つの書き込みがあり、親ノードを更新するために1つの追加の書き込みがあります。親ノードもいっぱいだった場合、それがどのように増加するかを確認できます。O(logn)
になります。ただし、これらはメモリ内で実行されるため、Bツリーのディスクでの対数演算よりも桁違いに高速であることを常に念頭に置いてください。完全を期すために、書き込みはクラッシュリカバリのために先行書き込みログにも書き込まれることを言及する必要があります。ただし、これらはすべて順次書き込みであるため、Bツリーのランダム書き込みよりもはるかに効率的であると予想されます。明らかになると、これら2つのアプローチの比較ははるかに複雑になります。具体的な比較を提供するための非常に単純化された試みでは、次のように言えるでしょう。
参考文献
LSMツリーは、構造化されたストレージエンジン上のBツリーよりも優れています。ランダム書き込みをaofに変換します。これがLSM-Tree srcです: https://github.com/shuttler/lsmtree