SQL INDEX-仕組み


19

データベースSQLに関する私の知識は、ほとんど大学のクラスに基づいています。とにかく、私はデータベースで作業していた会社で数ヶ月(ほぼ1年)過ごしました。

私は数冊の本を読んでいると私は、次のようなデータベースに関するいくつかの研修に参加したMySQLPostgreSQLSQLiteOracleともいくつかnonSQL dbのように、私たちMongoDBRedisElasticSearchなど

私が言ったように、私は初心者であり、多くの知識が不足していますが、今日、誰かが私の初心者の知識に完全に反することを話しました。

説明させてください。SQLデータベースを使用Personして、内部にレコードがほとんどない単純なテーブルを作成しましょう。

id | name   | age
-----------------
1  | Alex   | 24
2  | Brad   | 34
3  | Chris  | 29
4  | David  | 28
5  | Eric   | 18
6  | Fred   | 42
7  | Greg   | 65
8  | Hubert | 53
9  | Irvin  | 17
10 | John   | 19
11 | Karl   | 23

今、それは私が焦点を当てたい部分です- idですINDEX

これまでのところ、私はそれがこのように機能すると思った:テーブルが作成されているときINDEXは空です。テーブルに新しいレコードを追加するINDEXと、いくつかのアルゴリズムに基づいて再計算されます。例えば:

1つずつグループ化する:

1    ... N
N+1  ... 2N
     ...
XN+1 ... (X+1)N

だから、私の例ではsize = 11 elements、次のN = 3ようになります:

id | name   | age
-----------------
1  | Alex   | 24     // group0
2  | Brad   | 34     // group0
3  | Chris  | 29     // group0
4  | David  | 28     // group1
5  | Eric   | 18     // group1
6  | Fred   | 42     // group1
7  | Greg   | 65     // group2
8  | Hubert | 53     // group2
9  | Irvin  | 17     // group2
10 | John   | 19     // group3
11 | Karl   | 23     // group3

したがって、クエリを使用しているときSELECT * FROM Person WHERE id = 8は、いくつかの簡単な計算が行わ8 / 3 = 2れるため、このオブジェクトを検索する必要がgroup2あり、この行が返されます。

8  | Hubert | 53

ここに画像の説明を入力してください

このアプローチは時間内O(k)に機能しk << sizeます。もちろん、グループで行を整理するアルゴリズムは確かにはるかに複雑ですが、この単純な例は私の視点を示していると思います。

それで、今日、私に示された別のアプローチを提示したいと思います。

もう一度この表を見てみましょう。

id | name   | age
-----------------
1  | Alex   | 24
2  | Brad   | 34
3  | Chris  | 29
4  | David  | 28
5  | Eric   | 18
6  | Fred   | 42
7  | Greg   | 65
8  | Hubert | 53
9  | Irvin  | 17
10 | John   | 19
11 | Karl   | 23

現在、このidの行にHashmapマップidする(実際には、それはハッシュマップです)に似たものを作成していますaddress。まあ言ってみれば:

id | addr 
---------
1  | @0001
2  | @0010
3  | @0011
4  | @0100
5  | @0101
6  | @0110
7  | @0111
8  | @1000
9  | @1001
10 | @1010
11 | @1011

だから今、私が自分のクエリを実行しているとき: SELECT * FROM Person WHERE id = 8

id = 8メモリ内のアドレスに直接マップされ、行が返されます。もちろん、これの複雑さはですO(1)

だから今、私はいくつかの質問があります。

1.両方のソリューションの欠点と欠点は何ですか?

2.現在のデータベースの実装で人気があるのはどれですか?たぶん異なるDBは異なるアプローチを使用していますか?

3.非SQLデータベースに存在しますか?

前もって感謝します


比較

               |      B-tree     |   Hash Table
----------------------------------------------------
----------------   one element   -------------------
----------------------------------------------------
SEARCHING      |  O(log(N))      | O(1) -> O(N)  
DELETING       |  O(log(N))      | O(1) -> O(N)
INSERTING      |  O(log(N))      | O(1) -> O(N)
SPACE          |  O(N)           | O(N)
----------------------------------------------------
----------------    k elements   -------------------
----------------------------------------------------
SEARCHING      |  k + O(log(N))  | k * O(1) -> k * O(N)
DELETING       |  k + O(log(N))  | k * O(1) -> k * O(N)
INSERTING      |  k + O(log(N))  | k * O(1) -> k * O(N)
SPACE          |  O(N)           | O(N)

N-レコード数

私は正しいですか?各挿入/削除後にBツリーハッシュテーブルを再構築するコストはどうですか?Bツリーの場合、いくつかのポインターを変更する必要がありますが、バランスの取れたBツリーの場合は、より多くの努力が必要です。また、ハッシュテーブルの場合、特に操作で競合が発生する場合は、ほとんど操作を行う必要がありません。


2
2番目の方法では、ハッシュインデックスを記述しています。O(1)あなたについての部分はそれを正しくしました!最初の方法では、Bツリーインデックスを記述しているように見えますが、誤解があります。何の計算(3除算か何か)がありませんツリーは、より多くのレベル(それは木だ、それは大きな、小さな、小さな枝を持っている、...、その後、葉:)があるとして、それはより複雑だ
ypercubeᵀᴹ

3
btree:en.m.wikipedia.org/wiki/B-treeは、この説明あなたの大学でのコースのアルゴリズムはありませんでした驚い
Philᵀᴹ

@ypercubeこんにちは、ご回答ありがとうございます。私が書いたのと同じように:Of course, an alghoritm to organise rows in groups is for sure much more complicated but I think this simple example shows my point of view.もちろん、それははるかにはるかに複雑であることを知っています。だから最後に、コードINDEXで私のソリューション(1stまたは2nd)のどれがこの実際のソリューションに近いと言っていますか?そして、に基づいてレコードにアクセスするのに必要な時間はどうでしょうかINDEX。本当にO(1)?Bツリーインデックスを使用すると、のように聞こえますO(log2(N))。私は正しいですか?
ruhungry

@FreshPhilOfSO私は推測します(さらに、私は確信しています)、それについてのいくつかの講義でした。おそらく、私は...何かを逃した
ruhungry

ElasticSearchはBツリーとは全く異なる転置インデックス、使用elastic.co/blog/found-elasticsearch-from-the-bottom-up
LLUISマルティネス

回答:


12

基本的には、Bツリーインデックスとハッシュインデックスについて説明しています。どちらにも場所がありますが、両方とも異なる仕事に最適です。

長所と短所

Bツリー(およびB +ツリー)インデックスは通常、バランスが取れています。つまり、値の検索には、ツリー内のどこにあるかに関係なく、常に同じ時間がかかります(O(log n))。一般に、ツリー内のレベルの数は制限されているため、「より深く」ではなく「より広く」なる傾向があります。ただし、小さなデータセットの場合、Bツリーの保守と使用のコストは、すべての行を読み取るだけではありません。Bツリーインデックスは、大きなデータセット、選択性の低いデータセット、または1つのオブジェクトだけでなくオブジェクトの範囲を選択するデータセットに適しています。

ハッシュテーブルは、小さなデータセットに最適です。ハッシュインデックスには、使用されるハッシュアルゴリズムに応じて、事前定義された数のハッシュバケットがあります。これは、特定のハッシュアルゴリズムは非常に多くの一意のハッシュしか生成できないため、「より広く」ではなく「より深く」しか取得できないためです。データベースエンジンが適切なバケットを見つけると、そのバケット内のすべてのオブジェクトを調べて、目的のバケットを見つけます。小さく選択性の高いデータセットでは、各バケットに含まれるオブジェクトの数は非常に少なく、非常に迅速に解決されます。データセットが大きくなると、バケットははるかに混雑します。そのため、必要なオブジェクトが小さなバケツにある場合や、バケツの先頭近くにある場合は、かなり早く戻ります。大きなバケツの端にある場合は、時間がかかります。インデックスのバランスが取れていないため、パフォーマンスはO(1)からO(n)のどこかになります。

人気

一般的に、私はBツリーに最も多く出会った。ビットマップインデックスは、カーディナリティの低い値の別のオプションでもあります(ブール値や性別を考えてください)。これは、使用可能なインデックスタイプに関して、データベースエンジンによって異なります。

NoSQL

NoSQLデータベースは間違いなくインデックスをサポートしています。ほとんどがBツリーまたはBツリーのバリエーションをサポートしています。ほとんどがハッシュインデックスもサポートしているようです。


4
B +ツリーのレベル数が固定されているとは思わない。私の知る限り、少なくともSQL Serverではそうではありません。
ypercubeᵀᴹ

1
それは本当だ。Bツリーには任意の数のレベルを設定できますが、通常は3または4に制限されています。答えを編集しました。
-sarme

こんにちは@sarme。私はあなたの答えが本当に好きです。それは多くを説明します。この質問に対する賞金を始めても構いませんか?誰かが面白いものを追加するかもしれません。
ruhungry

1
ビットマップインデックスのカーディナリティが低いという意味ではありませんか?
ミハイ14

1
そう、カーディナリティは低い。就寝時間の直前に質問に答えるのをやめなければなりません:)。回答が更新されました。
sarme

4

両方のソリューションの欠点と欠点は何ですか?2番目のソリューションでは、範囲スキャンを実行できません。単一のIDを選択するのに最適です。しかし、ID 3〜8が必要な場合はどうでしょうか。現実の世界では取得するO(1)* 6レコードではない個々のレコードをすべて取得する必要があります。HashMapインデックスを備えた大規模な本番データベースでは、異なるページのレコードを取得するため、ディスクにアクセスして6つの異なるページをメモリに読み込む必要があります。

Bツリー構造では、最初の状況が実際に実装される方法のように、IDはディスク上で連続し、1つのページにID 3〜8が保持される可能性があります。 。

現在のデータベースの実装でより人気があるのはどれですか?たぶん異なるDBは異なるアプローチを使用していますか?多くの異なるデータベースで大きな経験はありません。Sql Serverは主にBツリーを使用しますが、SQl 2014には特定のテーブルで使用できる新しいハッシュインデックスがいくつかあります。個別のレコードの取得に基づいて構築された多くのNo Sqlデータベースとキャッシュデータベースもハッシュインデックスを使用します。キャッシュはユーザーAのレコードが必要であり、範囲スキャンを必要としないため、これは理にかなっています。

非SQL dbに存在しますか?はい。postgressqlのインデックス作成ドキュメントをざっと見てみると、HashインデックスとB-Treeインデックスの両方をサポートしていることがわかります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.