BツリーとB +ツリーの違いは何ですか?


293

では、Bツリーは、両方保存することができ、内部および葉ノードにキーとデータを、しかし中にB +ツリーあなたはにデータを格納する必要がリーフノードのみ

b +ツリーで上記を行うことの利点はありますか?

直感的にはるかに高速に見えるので、どこでもb +ツリーではなくbツリーを使用しないのはなぜですか?

つまり、なぜキー(データ)をb +ツリーに複製する必要があるのですか?


37
彼らが言っているのは「B-Tree」対B + -Treeだと思います。マイナス記号ではなくハイフンを意味します。
STU

回答:


421

以下の画像は、B +ツリーとBツリーの違いを示しています。

B +ツリーの利点:

  • B +ツリーには内部ノードに関連付けられたデータがないため、より多くのキーをメモリのページに収めることができます。したがって、リーフノードにあるデータにアクセスするために必要なキャッシュミスは少なくなります。
  • B +ツリーのリーフノードはリンクされているため、ツリー内のすべてのオブジェクトのフルスキャンを実行するには、すべてのリーフノードを1回だけ直線的に通過する必要があります。一方、ABツリーでは、ツリー内のすべてのレベルのトラバーサルが必要になります。このフルツリートラバーサルには、B +リーフの線形トラバーサルよりも多くのキャッシュミスが含まれる可能性があります。

Bツリーの利点:

  • Bツリーには各キーのデータが含まれているため、頻繁にアクセスされるノードはルートの近くにある可能性があり、より高速にアクセスできます。

BおよびB +ツリー


2
リーフノードのエントリ数に制約はありますか?
TLE 2014

38
@TLEいい質問です!はい。ハードドライブは一度に最低1ページのメモリにアクセスするため、すべてのポインタを1ページのメモリに収めたいと考えています。リーフアクセスごとに1つのディスク読み取りのみを必要とするため、リーフへのポインタのページサイズを超えて割り当てたくありません。リーフにポインターのページサイズを設定し、別のポインターをこのリーフに追加する場合は、このノードの2つの子を作成し、リーフのポインターの半分を新しい子ごとに割り当てます。もちろん、木の高さを最小限に抑えるために、多少の変更が必要になる場合があります。これは役に立ちますか?
Rose Perrone、2014

Bツリーの各リーフノードの最後のポインターは、次のリーフノードを指す必要がありますよね?
camino

8
そのような古いスレッドをぶつけて申し訳ありませんが、caminoのコメントがどのように正しいかについての@Babyburgerのコメントは実際には真実ではありません。Bツリーには、実際にはリーフノードが接続されていません。B +、確かに。
Jason

優れた答えをありがとう、データベースコンテキストのB / B +ツリーでオブジェクトのフルスキャンが必要になるユースケースは何ですか?これは主に索引付けに使用されるため、検索ではツリー全体を正しくスキャンする必要がほとんどなく、代わりに索引パスを経由する必要がありますか?
シッダールタ2017

113

Bツリーに対するB +ツリーの主な利点は、データへのポインターを削除することで他のノードへのポインターをより多く詰め込むことができるため、ファンアウトが増加し、ツリーの深さが減少する可能性があることです。

欠点は、内部ノードで一致が見つかった可能性のある早期のアウトがないことです。ただし、どちらのデータ構造にもファンアウトが非常に多いため、一致の大部分はリーフノードで行われ、平均してB +ツリーがより効率的になります。


1
フルスキャンを実行するときの効率の違いが強調されるため、私はジェフの答えを好みます。
ローズペローネ

順序トラバーサルを使用してBツリーをトラバースすると、すべての値がO(n)時間でソートされた順序で読み取られるため、私は本当に混乱しています。各ツリーノードが物理ページサイズに対して最適なサイズに設定されている場合、物事はそれ以上最適ではないようです。逆に、b + treeの最初の(最小の)値に到達するためのコストはO(log n)であり、次にすべてのリーフをウォークスルーするためのコストはO(n)なので、合計コストはO(log n + n)です。これはより多くの作業とより多くのディスク読み取りであり、ツリーにはこのすべての追加データが含まれているため、理にかなっています。わかりません。
Eric

上記の文の「ファンアウト」の別の言葉は何でしょうか?
ホルヘブカラン2016

3
@JorgeBucaranのファンアウト=ノードから出てくるエッジの数
バンメン

33

ターミナルノードはリンクリストを形成するため、B +ツリーは、ツリーがインデックス付けするすべてのデータを調べる場合と同様に、フルスキャンを実行する方がはるかに簡単でパフォーマンスが高くなります。Bツリーでフルスキャンを行うには、すべてのデータを見つけるためにフルツリートラバーサルを行う必要があります。

一方、Bツリーは、特にツリーがRAMまたはその他の非ブロックストレージにある場合に、シーク(キーで特定のデータの一部を探す)を行うと高速になります。ツリーでよく使用されるノードを昇格できるため、データにアクセスするために必要な比較が少なくなります。


1
次に同意しますか?B +ツリーは、すべてのデータにわたって順次読み取りが行われる可能性があるため、葉を横切ることができる状況で使用されます。Bツリーはランダムアクセスの状況に理想的ですが、
JDPeckham 2017

31
  1. Bツリーでは、検索キーとデータが内部ノードまたはリーフノードに格納されます。ただし、B +ツリーでは、データはリーフノードにのみ保存されます。
  2. B +ツリーのフルスキャンは、すべてのデータがリーフノードにあるため、非常に簡単です。Bツリーの完全スキャンには、完全走査が必要です。
  3. Bツリーでは、データはリーフノードまたは内部ノードにあります。内部ノードの削除は非常に複雑です。B +ツリーでは、データはリーフノードでのみ見つかります。葉ノードの削除は簡単です。
  4. Bツリーへの挿入は、B +ツリーよりも複雑です。
  5. B +ツリーは冗長な検索キーを格納しますが、Bツリーには冗長な値はありません。
  6. B +ツリーでは、リーフノードデータは順次リンクリストとして順序付けされますが、Bツリーでは、リンクリストを使用してリーフノードを格納できません。多くのデータベースシステムの実装では、B +ツリーの単純な構造が好まれます。

15

データベースシステムの概念の例5

B +ツリー B +ツリー

対応するBツリー Bツリー


5
Bツリーにノードの子へのリンクがあるとは思いません。たとえば、Clearview bucketからへMianus Bucket。どちらにしてもDowntown bucket、Bツリーでインデックススキャンを実行したい場合に検索する対象が多いため、これを行うのはあまり意味がありません(バックトラックが必要です)。どこでこれを手に入れましたか?
エヴァンキャロル

1
@EvanCarrollデータベースシステムの概念5番目、おそらく作成者に確認する必要があります:)
camino

11

「はるかに高速」を定義します。漸近的にはそれらはほぼ同じです。違いは、セカンダリストレージをどのように利用するかです。BツリーB +ツリーに関するウィキペディアの記事は、かなり信頼できるようです。


2
私はチャーリーに同意します。Bツリーの1つのノードは1つのセカンダリメモリページまたはブロックを表すため、あるノードから別のノードへの移行には、時間のかかるページ変更が必要です。

11

Adegoke A、Amit

このセクションで説明するように、人々が見逃している重要な点の1つは、データとポインタの違いです。

ポインタ:他のノードへのポインタ。

データ:-データベースインデックスのコンテキストでは、データは別の場所にある実際のデータ(行)への単なるポインタです。

したがって、Bツリーの場合、各ノードには3つの情報キー、キーに関連付けられたデータへのポインター、および子ノードへのポインターがあります。

B +ツリーでは、内部ノードはキーと子ノードへのポインタを保持し、リーフノードはキーと関連データへのポインタを保持します。これにより、特定のサイズのノードでより多くのキーを使用できます。ノードのサイズは主にブロックサイズによって決まります。

ノードごとにより多くのキーを持つことの利点は上で十分に説明されているので、タイピングの労力を節約します。


10

B +ツリーは、ブロックベースのストレージ(例:ハードディスク)に特に適しています。これを念頭に置くと、たとえば(頭の上から)いくつかの利点が得られます。

  • 高ファンアウト/低深度:つまり、データにアクセスするために必要なブロックを少なくする必要があります。ポインターとデータが混在していると、読み取りごとにポインターが少なくなるため、データに到達するためにシークを増やす必要があります。

  • シンプルで一貫性のあるブロックストレージ:内部ノードにはN個のポインターがあり、他には何もありません。リーフノードにはデータがあり、他にはありません。これにより、解析、デバッグ、再構築が簡単になります。

  • キー密度が高いということは、トップノードがほぼ確実にキャッシュ上にあることを意味します。多くの場合、すべての内部ノードがすばやくキャッシュされるため、データアクセスだけがディスクにアクセスする必要があります。


2
主にメモリ内ツリー用。しかし、赤黒木、スキップリストなど、他の一般的なオプションがあります。
ハビエル

Bツリーは、効率的なブロックベースのストレージ用にも設計されており、ノードアクセスの漸近的な数を制限します。そうでなければ、ランダムアクセスでメモリのようなストレージメディアを使用している場合、赤黒木などの自己均衡バイナリツリーを使用してより良い結果を得ることができます。
dionyziz 2012

最初のポイントは、「より多くのシーク」ではなく「より少ないシーク」と言ってはなりません。深度が小さい->シークが少ない
ジェシー

1
@ジェシー:ファンアウトが高い=>深度が低い=>シークが少ないが、データとポインターを混在させると、ポインターが少なくなる=>ファンアウトが低い=>深度が増える=>シークが増える
ハビエル

1
@AdegokeA:B + treeには2種類のノードがあります。キーとポインタのみを持つ内部ノードで、データはありません。リーフノード、データあり、ポインタなし。各内部ノードで最大数のキーを使用できます。内部ノードにデータを保存すると、ポインタの数が少なくなり、ツリーの高さが高くなります。
ハビエル

5

B +ツリーでは、ポインターのみが内部ノードに格納されるため、そのサイズはBツリーの内部ノード(両方のデータ+キーを格納する)よりも大幅に小さくなります。したがって、B +ツリーのインデックスは、単一のディスク読み取りで外部ストレージからフェッチされ、ターゲットの場所を見つけるために処理されます。Bツリーの場合は、意思決定プロセスごとにディスク読み取りが必要です。私は私のポイントを明確にしたいと思います!:)


4

**

Bツリーの主な欠点は、キーを順番にたどることが難しいことです。B +ツリーは、Bツリーの高速ランダムアクセスプロパティを保持しながら、高速シーケンシャルアクセスも可能にします。

** ref:C //を使用したデータ構造著者:Aaro M Tenenbaum

http://books.google.co.in/books?id=X0Cd1Pr2W0gC&pg=PA456&lpg=PA456&dq=drawback+of+B-Tree+is+the+difficulty+of+Traversing+the+keys+sequentially&source=bl&ots=pGcPQSEJMS&sig= F9MY7zEXYAMVKl_Sg4W-0LTRor8&hl = ja&sa = X&ei = nD5AUbeeH4zwrQe12oCYAQ&ved = 0CDsQ6AEwAg#v = onepage&q = drawback%20of%20B-Tree%20is%20the%20difficulty%20of%20false2020%20the%fequentials%20of%20equkeys%20false20f20%20falsekeys%20falsekeys%20falsekeys%20falsekeys%20false20


1
これは正解だったはずです。つまり、参照の局所性です。
Theodore Zographos

2

一例を挙げましょう。行ごとに巨大なデータを持つテーブルがあります。つまり、オブジェクトのすべてのインスタンスはビッグです。

ここでBツリーを使用する場合、ほとんどの時間はデータのあるページのスキャンに費やされます-これは役に立たないものです。データベースでは、オブジェクトデータのスキャンを回避するためにB +ツリーを使用する理由です。

B +ツリーは、データからキーを分離します。

ただし、データサイズが小さい場合は、Bツリーと同じようにキーを使用して保存できます。


1
「ここでBツリーを使用する場合、ほとんどの時間はデータのあるページのスキャンに費やされます」-必要ありません。Bツリーノードは、ディスク上のデータへの「ポインタ」のみを保持でき、データ自体は保持できません。
TT_ 2013

2

B-treeとB + treeの主な違いは、B-treeは検索キー値の冗長なストレージを排除することです。検索キーはB-treeで繰り返されないため、より少ないツリーノードを使用してインデックスを保存できない場合がありますただし、非リーフノードに表示される検索キーはBツリーの他の場所には表示されないため、非リーフノードの各検索キーに追加のポインターフィールドを含める必要があります。繰り返しが発生せず、大きなインデックスに使用できるため、これらはBツリーのスペース上の利点です。


1
興味深いことに、繰り返しに関する考え方はここでの返信の中で一意であり、bツリーの順序トラバーサルがbツリーの順序トラバーサルより効率的であるよりも意味があります。私が知る限り、それは完全に正しくないか、または全体ではありません.bツリーのトラバーサルはO(n)であり、b +ツリーで最小のノードを見つけることはO(log n)であり、次にそれに加えて、各葉をトラバースするのはO(n)です。ただし、ブールフィールドのように、値の範囲が狭いものにインデックスを付ける場合、b +ツリーは処理が重複するため、bツリーよりもはるかに理にかなっています。
Eric

1

B + treeは、ツリーのルートからリーフまでのすべてのパスが同じ長さであり、ツリーの各非リーフノードが[n / 2]から[n]までの子を持つバランスの取れたツリーです。nは特定の木のために修正されました。インデックスページとデータページが含まれています。バイナリツリーには、親ノードごとに2つの子しかありません。B+ツリーには、親ノードごとに可変数の子を含めることができます


1
明確にするために、Bツリーはバイナリツリーではありません。実際、BツリーとB +ツリーは、バイナリツリーよりも構築と使用方法が互いに近いです。Wikiの記事は、定義をクリアするのに役立ちます-B + TreeB Tree、およびBinary Tree
uutsav

1

B +ツリーの1つの可能な用途は、ツリーが非常に大きくなり、使用可能なメモリに収まらない状況に適していることです。したがって、通常は複数のI / Oを実行することになります。
実際にはメモリに収まる場合でもB +ツリーが使用され、キャッシュマネージャがそれを永続的に保持することがよくあります。ただし、これは一般的なケースではなく特殊なケースであり、キャッシュポリシーはB +ツリーのメンテナンスとは別のものです。

また、B +ツリーでは、リーフページがリンクリスト(または二重リンクリスト)でリンクされ、トラバーサル(範囲検索、並べ替えなど)が最適化されます。したがって、ポインターの数は、使用される特定のアルゴリズムの関数です。


これはなぜ我々はどこにでも代わりにB +木のB-木を使用してはならないことの質問への答えである:)
スタックプログラマ

3
しかし、私たちが知る限り、あなたの答えでBツリーがまったく同じように機能することができる片側だけを説明しました。OPは違いを説明するように求め、あなたは一方についてのみ話し、もう一方については話しませんでした。1つの円でベン図を作成することはできません。
Malfist 2009年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.