データセットのサイズが大きくなるにつれてインデックス作成が非常に重要になることを考えると、データベースに依存しないレベルでインデックス作成がどのように機能するかを誰か説明できますか?
フィールドにインデックスを付けるためのクエリについては、データベース列にインデックスを付ける方法を参照してください。
データセットのサイズが大きくなるにつれてインデックス作成が非常に重要になることを考えると、データベースに依存しないレベルでインデックス作成がどのように機能するかを誰か説明できますか?
フィールドにインデックスを付けるためのクエリについては、データベース列にインデックスを付ける方法を参照してください。
なぜそれが必要なのですか?
データがディスクベースのストレージ デバイスに保存される場合、データはデータのブロックとして保存されます。これらのブロック全体がアクセスされるため、アトミック ディスク アクセス操作になります。ディスク ブロックは、リンクされたリストとほとんど同じように構造化されています。両方とも、データのセクション、次のノード (またはブロック) の場所へのポインターを含み、両方とも連続して格納する必要はありません。
多くのレコードは 1 つのフィールドでしかソートできないため、ソートされていないフィールドを検索するには、(N+1)/2
(平均して) ブロック アクセスを必要とする線形検索が必要であると言えN
ます。テーブルが広がります。そのフィールドが非キー フィールド (つまり、一意のエントリを含まない) の場合、N
ブロック アクセス時にテーブルスペース全体を検索する必要があります。
一方、ソートされたフィールドでは、log2 N
ブロック アクセスを持つバイナリ検索を使用できます。また、データは非キー フィールドを指定してソートされるため、より高い値が見つかったら、テーブルの残りの部分で重複する値を検索する必要はありません。したがって、パフォーマンスの向上はかなりのものです。
索引付けとは
索引付けは、複数のフィールドで多数のレコードをソートする方法です。テーブル内のフィールドにインデックスを作成すると、フィールド値を保持する別のデータ構造と、関連するレコードへのポインターが作成されます。次に、このインデックス構造がソートされ、バイナリ検索を実行できるようになります。
インデックス作成の欠点は、インデックスが MyISAM エンジンを使用してテーブルに一緒に格納されるため、これらのインデックスがディスク上に追加のスペースを必要とすることです。同じテーブル内の多くのフィールドがインデックス化されている場合、このファイルは基礎となるファイル システムのサイズ制限にすぐに達する可能性があります。 .
それはどのように機能しますか?
まず、サンプル データベース テーブル スキーマの概要を説明しましょう。
フィールド名 データ型 ディスク上のサイズ id (主キー) Unsigned INT 4 バイト firstName Char(50) 50 バイト lastName Char(50) 50 バイト emailAddress Char(100) 100 バイト
注: varchar の代わりに char を使用して、ディスク値の正確なサイズを考慮しました。このサンプル データベースには 500 万行が含まれており、インデックスが作成されていません。いくつかのクエリのパフォーマンスが分析されます。これらは、id (ソートされたキー フィールド) を使用するクエリと、 firstName (非キーでソートされていないフィールド) を使用するクエリです。
例 1 -ソートされたフィールドとソートされていないフィールド
r = 5,000,000
レコード長がバイトの固定サイズのレコードのサンプル データベースがあり、デフォルトのブロック サイズバイトR = 204
を使用する MyISAM エンジンを使用してテーブルに格納されているとします。B = 1,024
テーブルのブロック係数は、bfr = (B/R) = 1024/204 = 5
ディスク ブロックあたりのレコードになります。テーブルを保持するために必要なブロックの総数は、blocks ですN = (r/bfr) = 5000000/5 = 1,000,000
。
N/2 = 500,000
id フィールドの線形検索では、id フィールドがキー フィールドである場合、値を見つけるためにブロック アクセスの平均が必要になります。ただし、id フィールドもソートされるため、log2 1000000 = 19.93 = 20
ブロックアクセスの平均を必要とするバイナリ検索を実行できます。これが劇的な改善であることがすぐにわかります。
現在、firstNameフィールドはソートされておらず、キー フィールドでもないため、バイナリ検索は不可能であり、値も一意ではないため、正確なN = 1,000,000
ブロック アクセスをテーブルで最後まで検索する必要があります。索引付けが修正を目指すのは、この状況です。
インデックス レコードにインデックス付きフィールドと元のレコードへのポインタのみが含まれていることを考えると、インデックス レコードが指す複数フィールド レコードよりも小さくなるのは当然のことです。したがって、インデックス自体に必要なディスク ブロックは元のテーブルよりも少なくて済みます。したがって、反復処理に必要なブロック アクセスが少なくなります。firstNameフィールドのインデックスのスキーマを以下に示します。
フィールド名 データ型 ディスク上のサイズ firstName Char(50) 50 バイト (レコードポインタ) 特殊 4 バイト
注: MySQL のポインターの長さは、テーブルのサイズに応じて 2、3、4、または 5 バイトです。
例 2 -索引付け
r = 5,000,000
インデックス レコード長がR = 54
バイトで、デフォルトのブロック サイズ バイトを使用するレコードのサンプル データベースがあるとしB = 1,024
ます。インデックスのブロック係数は、bfr = (B/R) = 1024/54 = 18
ディスク ブロックあたりのレコードになります。インデックスを保持するために必要なブロックの総数は、blocks ですN = (r/bfr) = 5000000/18 = 277,778
。
これで、 firstNameフィールドを使用した検索で、インデックスを利用してパフォーマンスを向上させることができます。log2 277778 = 18.08 = 19
これにより、ブロックアクセスの平均を使用してインデックスのバイナリ検索が可能になります。実際のレコードのアドレスを見つけるには、読み取りにさらにブロック アクセスが必要であり、合計をブロック アクセスにします。これは、インデックスのないテーブルでfirstName19 + 1 = 20
の一致を見つけるために必要な 1,000,000 回のブロック アクセスとはかけ離れています。
いつ使用する必要がありますか?
インデックスの作成には追加のディスク領域が必要であり (上記の例から 277,778 ブロック余分に、約 28% 増加)、インデックスが多すぎるとファイル システムのサイズ制限に起因する問題が発生する可能性があるため、適切なインデックスを選択するには慎重に検討する必要があります。索引付けするフィールド。
インデックスはレコード内の一致するフィールドの検索を高速化するためにのみ使用されるため、出力のみに使用されるフィールドのインデックス作成は、挿入または削除操作を行う際のディスク容量と処理時間の浪費に過ぎないのは当然のことです。避けるべきです。また、バイナリ検索の性質上、データのカーディナリティまたは一意性も重要です。カーディナリティが 2 のフィールドでインデックスを作成すると、データが半分に分割されますが、カーディナリティが 1,000 の場合は、約 1,000 レコードが返されます。カーディナリティがこのように低いと、有効性が線形ソートに低下します。また、カーディナリティがレコード数の 30% 未満の場合、クエリ オプティマイザはインデックスの使用を回避し、実質的にインデックスをスペースの無駄にします。
インデックスは、データベース内の特定の列の検索を高速化する単なるデータ構造です。この構造は通常、b ツリーまたはハッシュ テーブルですが、他の論理構造にすることもできます。
初めて読んだのでとても参考になりました。ありがとうございました。
それ以来、インデックスを作成することのマイナス面についていくつかの洞察を得ました。1 つのインデックスを持つテーブル (UPDATE
またはINSERT
) に書き込むと、実際にはファイル システムで 2 つの書き込み操作が行われます。1 つはテーブル データ用、もう 1 つはインデックス データ用 (およびその再ソート (およびクラスター化されている場合はテーブル データの再ソート))。テーブルとインデックスが同じハードディスクにある場合、これにはより多くの時間がかかります。したがって、インデックス (ヒープ) のないテーブルでは、より迅速な書き込み操作が可能になります。(インデックスが 2 つある場合は、最終的に 3 つの書き込み操作が必要になるなど)
ただし、インデックス データとテーブル データ用に 2 つの異なるハードディスク上に 2 つの異なる場所を定義すると、時間のコストが増加するという問題を軽減または解消できます。これには、目的のハードディスク上の対応するファイルを含む追加のファイル グループの定義と、必要に応じてテーブル/インデックスの場所の定義が必要です。
インデックスのもう 1 つの問題は、データが挿入されるにつれて断片化することです。REORGANIZE
それを行うには、ルーチンを作成する必要があります。
特定のシナリオでは、ヒープはインデックスを持つテーブルよりも役立ちます。
例:- 競合する書き込みが多数あるが、レポート用に営業時間外に毎晩 1 回のみ読み取りを行う場合。
また、クラスター化インデックスと非クラスター化インデックスの違いも重要です。
私を助けてくれました:-クラスター化インデックスと非クラスター化インデックスは実際には何を意味しますか?
ここで、クエリを実行して、'Abc' という名前の従業員のすべての詳細を検索するとします。
SELECT * FROM Employee
WHERE Employee_Name = 'Abc'
インデックスがないとどうなるでしょうか?
データベース ソフトウェアは、従業員テーブルのすべての行を文字通り調べて、その行の Employee_Name が「Abc」であるかどうかを確認する必要があります。そして、その中に「Abc」という名前を持つすべての行が必要なため、「 Abc」という名前を持つ行が 1 つだけ見つかったら、探すのをやめることはできません。したがって、最後の行までのすべての行を検索する必要があります。つまり、このシナリオでは、「Abc」という名前の行を見つけるためにデータベースで数千行を調べる必要があります。これは、フル テーブル スキャンと呼ばれるものです。
データベース インデックスがパフォーマンスにどのように役立つか
インデックスを持つことの全体的なポイントは、調べる必要があるテーブル内のレコード/行の数を本質的に削減することにより、検索クエリを高速化することです。インデックスは、テーブルの特定の列の値を格納するデータ構造 (最も一般的には B ツリー) です。
B ツリー インデックスはどのように機能しますか?
B ツリーがインデックスの最も一般的なデータ構造である理由は、ルックアップ、削除、および挿入をすべて対数時間で実行できるため、時間効率が高いという事実によるものです。また、B ツリーがより一般的に使用されるもう 1 つの主な理由は、B ツリー内に格納されているデータを並べ替えることができるためです。通常、RDBMS は、実際にインデックスに使用されるデータ構造を決定します。ただし、特定の RDBMS のシナリオでは、インデックス自体を作成するときに、データベースで使用するデータ構造を実際に指定できます。
ハッシュ テーブル インデックスはどのように機能しますか?
ハッシュ インデックスが使用される理由は、値を検索するだけの場合、ハッシュ テーブルが非常に効率的だからです。そのため、文字列と等しいかどうかを比較するクエリは、ハッシュ インデックスを使用すると、値を非常に高速に取得できます。
たとえば、前に説明したクエリは、Employee_Name 列に作成されたハッシュ インデックスの恩恵を受ける可能性があります。ハッシュ インデックスが機能する方法は、列の値がハッシュ テーブルのキーになり、そのキーにマップされる実際の値がテーブル内の行データへのポインターになるというものです。ハッシュ テーブルは基本的に連想配列であるため、一般的なエントリは「Abc => 0x28939」のようになります。ここで、0x28939 は、Abc がメモリに格納されているテーブル行への参照です。ハッシュ テーブル インデックスで "Abc" のような値を検索し、メモリ内の行への参照を取得する方が、テーブルをスキャンして Employee_Name 列に "Abc" の値を持つすべての行を見つけるよりもはるかに高速です。
ハッシュインデックスの欠点
ハッシュ テーブルはソートされたデータ構造ではありません。また、ハッシュ インデックスが役に立たないタイプのクエリが多数あります。たとえば、40 歳未満のすべての従業員を検索するとします。ハッシュ テーブル インデックスを使用してそれを行うにはどうすればよいでしょうか。ハッシュ テーブルはキーと値のペアの検索にのみ適しているため、これは不可能です。つまり、同等性をチェックするクエリを意味します。
データベース インデックスの中身は正確には何ですか? これで、テーブルの列にデータベース インデックスが作成され、インデックスがその特定の列に値を格納することがわかりました。ただし、データベース インデックスは、同じテーブルの他の列に値を格納しないことを理解することが重要です。たとえば、Employee_Name 列にインデックスを作成した場合、これは Employee_Age および Employee_Address 列の値もインデックスに格納されないことを意味します。他のすべての列をインデックスに格納しただけでは、テーブル全体のコピーをもう 1 つ作成するのと同じようになり、スペースを取りすぎて非常に非効率的になります。
データベースはインデックスをいつ使用するかをどのように認識しますか? 「SELECT * FROM Employee WHERE Employee_Name = 'Abc' 」のようなクエリが実行されると、データベースはクエリ対象の列にインデックスがあるかどうかを確認します。Employee_Name 列にインデックスが作成されていると仮定すると、データベースは、インデックスを使用して検索対象の値を見つけることが実際に意味があるかどうかを判断する必要があります。これは、データベース インデックスを使用する方が実際には効率が悪い場合があるためです。 、テーブル全体をスキャンするだけでより効率的です。
データベース インデックスのコストはいくらですか?
スペースを占有します。また、テーブルが大きいほど、インデックスも大きくなります。インデックスに関するもう 1 つのパフォーマンス ヒットは、対応するテーブルの行を追加、削除、または更新するたびに、インデックスに対して同じ操作を実行する必要があるという事実です。インデックスには、インデックスがカバーするテーブル列にあるものと同じ分までのデータが含まれている必要があることに注意してください。
原則として、インデックス付きの列のデータが頻繁にクエリされる場合にのみ、テーブルにインデックスを作成する必要があります。
こちらもご覧ください
インデックスは、特定の列の値をテーブルに格納するデータ構造に他なりません。テーブルの列にインデックスが作成されます。
User
例: と という3 つの列Name
を持つデータベース テーブルがありAge
ますAddress
。テーブルUser
に数千の行があるとします。
ここで、クエリを実行して、'John' という名前のユーザーのすべての詳細を検索するとします。次のクエリを実行すると:
SELECT * FROM User
WHERE Name = 'John'
データベース ソフトウェアは、その行の が「John」であるかどうかを確認するために、文字通りUser
テーブルのすべての行を調べる必要があります。Name
これには長い時間がかかります。
これがindex
私たちを助けるところです: index は本質的に調べる必要があるテーブルのレコード/行の数を減らすことによって検索クエリをスピードアップするために使用されます.
索引の作成方法:
CREATE INDEX name_index
ON User (Name)
Anindex
は1 つのテーブルの列値 (例: John) で構成され、それらの値はデータ構造に格納されます。
したがって、データベースはインデックスを使用して John という名前の従業員を検索します。これは、インデックスがおそらくユーザー名のアルファベット順にソートされるためです。また、並べ替えられているため、「J」で始まるすべての名前がインデックス内で隣り合っているため、名前の検索がはるかに高速になります。
簡単な提案..インデックス作成には追加の書き込みとストレージスペースがかかるため、アプリケーションでより多くの挿入/更新操作が必要な場合は、インデックスなしのテーブルを使用することをお勧めしますが、より多くのデータ取得操作が必要な場合は、インデックス付きを使用する必要がありますテーブル。
データベース インデックスは本のインデックスと考えてください。
犬に関する本を持っていて、たとえばジャーマン シェパードについての情報を見つけたい場合、もちろん本のすべてのページをめくって探しているものを見つけることができますが、もちろんこれには時間がかかります。とても早い。
もう 1 つのオプションは、本の [索引] セクションに移動し、探しているエンティティの名前 (この例ではジャーマン シェパード) を使用して探しているものを見つけ、ページ番号を見て、探しているものを見つけることです。探しているものをすばやく見つけます。
データベースでは、ページ番号は、エンティティが配置されているディスク上のアドレスにデータベースを指示するポインターと呼ばれます。同じジャーマン シェパードのアナロジーを使用すると、次のようなものを作成できます (「ジャーマン シェパード」、0x77129)。ここ0x77129
で、 はジャーマン シェパードの行データが格納されているディスク上のアドレスです。
簡単に言えば、インデックスとは、クエリ検索を高速化するために、特定の列の値をテーブルに格納するデータ構造です。