web-dev-qa-db-ja.com

列がインデックス付けされている場合、コンピューターがテーブル全体を読み取る必要がないのはなぜですか?

2つの列を持つテーブルに100兆レコードがあるとします。そして、カラム#2が何かと等しいレコードを見つけたいと思います。

列#2にインデックスが付けられている場合、結果はすぐに返されますが、そうでない場合、コンピューターはテーブル全体を読み取る必要があるため、時間がかかります。

列がインデックス付けされている場合、コンピューターがテーブル全体を読み取る必要がないのはなぜですか?どのようにして、テーブルを読み取らずに結果が何であるかを知ることができますか?

12
user1806244

本の「索引」は、IMOという素晴らしい比喩ではありません。より良い比喩は、単語を辞書で調べようとすることです。複数のボリュームで構成される大規模な辞書であるOxford English Dictionary(OED)で単語を検索するとします。

enter image description here

もちろん、OEDの単語はアルファベット順にソートされており、単語を簡単に検索できます。しかし、単語が並べ替えられていない場合はどうなりますか?辞書にランダムな順序で追加された場合はどうなりますか?

この仮想の並べ替えられていない辞書で単語「quadrillion」を検索し、通常の並べ替えられた辞書で同じ単語を検索することと比較する思考実験を行ってみましょう。

辞書に10,000ページあり、各ページに1つのWordがあると仮定します。

ソートされていない辞書

アルファベット順にソートされていない辞書で「quadrillion」という単語を見つけるには、片方の端から始めなければなりません(たとえば1ページ目)。 1ページ目の単語が「4兆」の場合、おめでとうございます。もちろん、辞書はランダムであるため、最初のページに「quadrillion」が存在しない可能性があります。つまり、「quadrillion」が見つかるまで、次のページをチェックしてから、次のページをチェックする必要があります。

ワード「quadrillion」を見つけるために(最悪の場合)何ページ見る必要がありますか?まあ、それらすべての可能性があります...たまたま「4兆」が辞書の最後のWordになる可能性があるため、最悪のシナリオでは10,000ページすべてを調べる必要があります。

これは手に負えないほど退屈な作業であり、データベースのテーブルのすべての行を見るのに似ています。

ソートされた辞書

幸い、辞書areはアルファベット順にソートされているため、Wordを数週間ではなく数分で検索できます。辞書で単語を見つける方法は誰もが知っていますが、それを実行するためのアルゴリズムを作成する必要があったと仮定します。そのアルゴリズムはどのように機能しますか?

  • 真ん中のページ(5,000)まで辞書を開き、そのページの単語「mellifluous」を読みます。
  • このWordは、(アルファベット順で)4兆よりも高いので、1兆は5,001ページから10,000ページの間のどこかにあるはずです。
  • 次に、5,001と10,000の中点である7,500ページに移動します。
  • このページの言葉は「サクロサンクト」です。これは「クアドリリオン」よりも低いため、クアドリリオンがページ5,001から7,500の間にあることがわかります。
  • 次に、5,001と7,500の中点である6,250に切り替えます。
  • ...
  • 残りのページを半分に分割し、Wordの半分を把握するこのプロセスを繰り返し、最終的に「4兆」を含むページを開いて完了です。

これは、並べ替えられていない辞書アルゴリズムと比べてどの程度効率的ですか?まだたくさんのページを見なければならなかったでしょう?

各ステップでページの半分を削除していることに気づくことで効率を計算できます。したがって、残りのページ数を数えることで、Wordに到達するために必要なステップ数を数えることができます。

  1. 10,000ページから始めます。
  2. 5,000ページに絞り込みます。
  3. その後、2,500。
  4. 1,250
  5. 625
  6. 312(小数点以下がある場合は切り捨てます)
  7. 156
  8. 78
  9. 39
  10. 19
  11. 9
  12. 4
  13. 2
  14. 1

残りの1ページに到達するまでに、確実に知っている探している単語が見つかったか、辞書に存在していないことがわかります。ステップ数を数えると、Wordを見つけるために14ページ(最悪の場合)を見さえすればよいことがわかります。これは、10,000ページすべてを表示するよりも大幅に改善されています。

より一般的には、最悪の場合のルックアップ時間はlog2(n)です。ここで、nはディクショナリ内のページ数です。 (あなたの答えが私のものと一致するかどうかを確かめるために自分で計算してみてください。)これは、log関数の成長が非常に遅いため、アルゴリズムにとって非常に望ましい特性です。辞書のページ数が10kではなく10億ページであったとしても、辞書内の特定の単語を見つけるのに30ステップしかかかりません。 (もう一度、自分で計算してみてください。)

これは、テーブルで行を検索するためにインデックスを使用するデータベースに似ています。

Bツリー

Bツリーは、ソートされた辞書で単語を見つけるために使用するアルゴリズムと同様のアルゴリズムを使用できるようにするデータ構造です。これは、基本的なコンピュータサイエンスにおいて非常に重要なデータ構造です。

http://en.wikipedia.org/wiki/B-tree

多くのデータベースインデックスは、実際には内部ではBツリーです。

衒学

あなたが言った:

列#2にインデックスが付けられている場合、結果はすぐに返されますが、そうでない場合、コンピューターはテーブル全体を読み取る必要があるため、時間がかかります

「すぐに」という部分は真実ではありません。それでも、参照する必要のあるアイテムをより多く実行するのに時間がかかる反復アルゴリズムです。これは非常に効率的なアルゴリズムであり、結果はfeel即時になる可能性がありますが、それはnot a constant time algorithmであることに注意することが重要です。

8
Mark E. Haase

基本的に、インデックスはorderedであり、順序付けられたデータセットを検索するときに、すべてのアイテムを検索して要素を見つける必要はありません。再探し;より速い方法があります。

データベースのインデックス作成について詳細に議論することは非常に難解になる可能性がありますが、これに答える最も簡単な方法は、 binary search などの手法を使用して、要素をはるかに迅速に見つけることです。 「私は1から100までの数字を考えています」という推測ゲームをプレイしたことがある人なら誰でも、直感的に明白です。あなたの推測が毎回半分に「検索」される値の数のサイズを削減する場合、100ではなく7推測以内の数値を常に推測する方法を知っていますか?データベースは、インデックス作成と非常によく似た処理を行います。

29
Mason Wheeler

コンピュータがテーブルを読み取らずに結果が何であるかを知っているということではありません。結果を見つけるために実際にはかなり多くの作業を行いますが、非常に高速であるため、瞬時に表示されます。しかし、はい、確かに、それはテーブル全体を読み取りません。

動作は実装に依存しますが、説明のために役立つ一般的な単純なアルゴリズムはbinary searchです。辞書で単語を見つける方法と同様に機能します。明らかに、単語を探すたびに辞書全体を読むわけではありませんよね。

あなたがしていることは、真ん中の近くのどこかで辞書を開くことです(アルゴリズムは正確な真ん中に行きますが、それはコンピューターが近似よりも簡単に精度を見つけるだけです)、そのページから1つの単語だけを読んで、あなたが探している言葉はあなたが読んだ言葉の前か後に来ます。前に来た場合は、本の後半を無視して、前半のみに焦点を当てます。それが後に来る場合、あなたは本の前半を無視し、後半のみに焦点を合わせます:次に、あなたが焦点を当てている半分の真ん中にページを開き、別の単語を読み、あなたの単語が来るかどうかを確認します正しいページが見つかるまで、前後にこの手順を繰り返します。

これが機能する理由は、辞書の単語が並べ替えられているためです。並べ替えられていない場合は、辞書全体を調べて単語を見つける必要があります。データベースでインデックスが行うことは、データのソートされたビューを提供することです。これにより、バイナリ検索を使用して値を見つけることができます。

バイナリ検索を使用すると、10ページの検索だけで1000ページの辞書からWordの正しいページを見つけることができ、32ページの検索で40億ページの辞書からWordの正しいページを見つけることができます。ご覧のように、sweetのように非線形にスケーリングします。

11
Mike Nakis

バイナリー豆

赤いゼリー豆の束と青いゼリー豆の束があります。

赤いジェリービーンズを左に、青いジェリービーンズを右に置きます。

赤いゼリー豆の左側の世界で、左側にそばかすのないもの、右側にそばかすの多いものを分離します。

だから今のようなものがあります

                    Root
              Reds/     \ Blues
           /     \
no freckles     freckles

さまざまな属性でツリーを分岐し続けることができます。最終的に、そばかすのある赤いジェリービーンを見つけたい場合は、2つの手順を実行するだけでよく、すべてのビーンを1つずつ拾って確認し、戻す必要はありません。そばかすのある小豆に達するまで新しいもの。

ジェリービーンズがいくつあっても、赤いものや青いものを見つけるのはとても簡単です。

ツリーは、データの違いを分岐することにより、同様に機能します(バイナリツリー、B +ツリー、トライなど)。


プリンセスホテル

索引付けは、データのパターンを効率的に活用するためのもう1つの方法です。

ホテルがあり、すべてのVIPを最上階に配置し、すべてのプリンセスを3階に配置し、すべての王を2階に配置したとします。

そうすれば、プリンセスを見つけたいときにすべての部屋を探す必要はありません。3階に行くだけです。シーク時間が大幅に短縮されます。

データでそれを行うことを想像してください。

したがって、インデックスはallデータではなく、すべてのデータの場所を示す単なるマップです。データに悪用可能なニースのパターンがいくつかある場合、インデックスにより検索が非常に効率的になります。

4
sova