データセットのサイズが大きくなると、インデックス付けが非常に重要になるので、データベースに依存しないレベルでインデックス付けがどのように機能するかを誰かが説明できますか?
フィールドにインデックスを付けるクエリの詳細については、データベースの列にインデックスを付ける方法をご覧ください。
データセットのサイズが大きくなると、インデックス付けが非常に重要になるので、データベースに依存しないレベルでインデックス付けがどのように機能するかを誰かが説明できますか?
フィールドにインデックスを付けるクエリの詳細については、データベースの列にインデックスを付ける方法をご覧ください。
回答:
なぜそれが必要なのですか?
データがディスクベースのストレージデバイスに保存される場合、データのブロックとして保存されます。これらのブロックは全体としてアクセスされるため、アトミックディスクアクセス操作になります。ディスクブロックは、リンクリストとほとんど同じ方法で構成されます。どちらにもデータのセクション、次のノード(またはブロック)の場所へのポインターが含まれており、両方を連続して格納する必要はありません。
いくつかのレコードは1つのフィールドでしか並べ替えることができないため、並べ替えられていないフィールドを検索するには、N/2
ブロックアクセス(平均)を必要とする線形検索が必要N
です。テーブルがまたがっています。そのフィールドが非キーフィールド(つまり、一意のエントリを含まない)の場合、N
ブロックアクセス時にテーブルスペース全体を検索する必要があります。
ソートされたフィールドでは、log2 N
ブロックアクセスのあるバイナリ検索を使用できます。また、非キーフィールドを指定してデータがソートされるため、より高い値が見つかれば、テーブルの残りの部分で重複する値を検索する必要はありません。したがって、パフォーマンスの向上はかなりのものです。
索引付けとは何ですか?
索引付けは、複数のフィールドで多数のレコードをソートする方法です。テーブルのフィールドにインデックスを作成すると、フィールド値を保持する別のデータ構造と、関連するレコードへのポインタが作成されます。次に、このインデックス構造がソートされ、バイナリ検索を実行できるようになります。
インデックス作成の欠点は、インデックスがMyISAMエンジンを使用してテーブルに一緒に格納されるため、これらのインデックスにはディスク上に追加のスペースが必要になることです。このファイルは、同じテーブル内の多くのフィールドにインデックスが作成されている場合、基になるファイルシステムのサイズ制限にすぐに達する可能性があります。 。
どのように機能しますか?
最初に、サンプルのデータベーステーブルスキーマの概要を説明します。
フィールド名データ型ディスク上のサイズ id(主キー)符号なし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
とすると、それらは、デフォルトのブロックサイズB = 1,024
バイトを使用しているMyISAMエンジンを使用してテーブルに格納されます。テーブルのブロック化因数は、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
ブロックアクセスの平均を伴うインデックスのバイナリ検索が可能になります。実際のレコードのアドレスを見つけるには、読み取りにさらにブロックアクセスが必要であり、合計で19 + 1 = 20
ブロックアクセスになるため、非インデックステーブルでfirstName一致を見つけるのに必要な1,000,000ブロックアクセスとはかけ離れています。
いつ使用すべきですか?
インデックスの作成には追加のディスク領域が必要であり(上記の例から277,778ブロック余分、最大28%増加)、インデックスが多すぎるとファイルシステムのサイズ制限に起因する問題が発生する可能性があるため、適切な選択を行うために慎重に検討する必要がありますインデックスを付けるフィールド。
インデックスは、レコード内の一致するフィールドの検索を高速化するためにのみ使用されるため、出力のみに使用されるインデックスフィールドは、挿入または削除操作を実行するときのディスクスペースと処理時間の無駄になるだけです。避けるべきです。また、バイナリ検索の性質を考えると、データのカーディナリティまたは一意性は重要です。カーディナリティが2のフィールドでインデックスを作成するとデータが半分に分割されますが、カーディナリティが1,000の場合は約1,000レコードが返されます。カーディナリティがこのように低い場合、効果は線形ソートに減少し、カーディナリティがレコード番号の30%未満の場合、クエリオプティマイザーはインデックスの使用を回避し、インデックスをスペースの無駄にします。
(N+1)/2
。考えられるすべてのケースのブロックアクセス数を合計し、それをケースの数で割ると、N*(N+1)/(2*n)
どちらがになるかがわかります(N+1)/2
。
古典的な例「本の索引」
1000ページの「本」を10章で割ったものを考えてください。各セクションは100ページです。
シンプルでしょ?
ここで、「Alchemist」という単語を含む特定のチャプターを検索するとします。索引ページがないと、書籍全体または章全体をスキャンする以外に選択肢はありません。すなわち:1000ページ。
この類推は、データベースの世界では「フルテーブルスキャン」として知られています。
しかし、インデックスページがあれば、どこに行けばいいのかわかります。さらに、重要な特定の章を検索するには、毎回、何度もインデックスページを確認する必要があります。一致するインデックスを見つけたら、残りをスキップして、その章に効率的にジャンプできます。
しかし、実際の1000ページに加えて、インデックスを表示するためにさらに10ページが必要になるため、合計で1010ページになります。
したがって、インデックスは、効率的なルックアップのために、インデックス付き列の値とインデックス付き行へのポインタをソートされた順序で格納する個別のセクションです。
学校では物事は簡単ですよね。:P
Library
またはGrocery Store
あなたは食料品店でインデックスを持っていないとイメージできますか? Where's The Beef?!? Oh its next to the Restrooms, a mop, and makeup
これを初めて読んだときは、とても役に立ちました。ありがとうございました。
それ以来、インデックスを作成することのマイナス面についていくつかの洞察を得ました。1つのインデックスでテーブル(UPDATE
またはINSERT
)に書き込む場合、実際にはファイルシステムで2つの書き込み操作があります。1つはテーブルデータ用で、もう1つはインデックスデータ用です(そしてそれを再ソートします(クラスタ化されている場合は、テーブルデータを再ソートします))。テーブルとインデックスが同じハードディスク上にある場合、これにより多くの時間がかかります。したがって、インデックス(ヒープ)のないテーブルは、より高速な書き込み操作を可能にします。(2つのインデックスがある場合、3つの書き込み操作が発生することになります)
ただし、インデックスデータとテーブルデータ用に2つの異なるハードディスク上の2つの異なる場所を定義すると、時間のコストが増加するという問題を軽減または解消できます。これには、必要なハードディスク上の対応するファイルを含む追加のファイルグループの定義と、必要に応じたテーブル/インデックスの場所の定義が必要です。
インデックスに関するもう1つの問題は、データが挿入されるときのインデックスの断片化です。REORGANIZE
それを行うには、ルーチンを作成する必要があります。
特定のシナリオでは、インデックスのあるテーブルよりもヒープの方が便利です。
例:-競合する書き込みが多数あるが、レポート作成のために営業時間外に夜間に1回だけ読み取る場合。
また、クラスター化インデックスと非クラスター化インデックスの違いもかなり重要です。
私を助けました:- クラスタ化インデックスと非クラスタ化インデックスは実際にはどういう意味ですか?
インデックスは、データベース内の特定の列の検索を高速化する単なるデータ構造です。この構造は通常、Bツリーまたはハッシュテーブルですが、他の論理構造でもかまいません。
次に、クエリを実行して、「Abc」という名前の従業員の詳細をすべて検索するとします。
SELECT * FROM Employee
WHERE Employee_Name = 'Abc'
インデックスがないとどうなりますか?
データベースソフトウェアは、文字どおりEmployeeテーブルのすべての行を調べて、その行のEmployee_Nameが 'Abc'かどうかを確認する必要があります。我々はその中に名前「ABC」ですべての行をしたいので、我々は名前「ABC」でただ一つの行を見つけたら、名前を持つ他の行があるかもしれませんのでそして、私たちは、探して停止することはできませんAbcの。したがって、最後の行までのすべての行を検索する必要があります。つまり、このシナリオでは数千の行をデータベースで調べて、「Abc」という名前の行を見つける必要があります。これはいわゆる全表スキャンです
データベースインデックスがパフォーマンスにどのように役立つか
インデックスを持つことの全体的なポイントは、調査する必要があるテーブルのレコード/行の数を本質的に削減することにより、検索クエリを高速化することです。インデックスは、テーブル内の特定の列の値を格納するデータ構造(最も一般的にはBツリー)です。
Bツリーインデックスはどのように機能しますか?
B-treeがインデックスの最も一般的なデータ構造である理由は、それらが時間効率が良いという事実によるものです-ルックアップ、削除、および挿入はすべて対数時間で実行できるためです。また、B-treeがより一般的に使用されるもう1つの主な理由は、B-tree内に格納されているデータをソートできるためです。RDBMSは通常、インデックスに実際に使用されるデータ構造を決定します。ただし、特定のRDBMSを使用する一部のシナリオでは、インデックス自体を作成するときに、データベースで使用するデータ構造を実際に指定できます。
ハッシュテーブルインデックスはどのように機能しますか?
ハッシュインデックスが使用される理由は、ハッシュテーブルは値を検索するだけの場合、非常に効率的だからです。そのため、文字列と等しいかどうかを比較するクエリは、ハッシュインデックスを使用すると非常に高速に値を取得できます。
たとえば、前に説明したクエリは、Employee_Name列に作成されたハッシュインデックスの恩恵を受けることができます。ハッシュインデックスが機能する方法は、列の値がハッシュテーブルへのキーとなり、そのキーにマップされた実際の値がテーブル内の行データへのポインターになるというものです。ハッシュテーブルは基本的に連想配列であるため、一般的なエントリは「Abc => 0x28939」のようになります。0x28939は、Abcがメモリに格納されているテーブル行への参照です。ハッシュテーブルインデックスで「Abc」などの値を検索し、メモリ内の行への参照を取得する方が、テーブルをスキャンしてEmployee_Name列の値が「Abc」であるすべての行を見つけるよりも明らかに高速です。
ハッシュインデックスの欠点
ハッシュテーブルは並べ替えられたデータ構造ではなく、ハッシュインデックスが役に立たない多くの種類のクエリがあります。たとえば、40歳未満のすべての従業員を検索するとします。ハッシュテーブルインデックスを使用してどうすればよいでしょうか。まあ、それは不可能です。ハッシュテーブルはキーと値のペアを検索する場合にのみ有効です。つまり、等価性をチェックするクエリです。
データベースインデックスの正確には何ですか? これで、データベースインデックスがテーブルの列に作成され、インデックスがその特定の列に値を格納することがわかりました。ただし、データベースインデックスは同じテーブルの他の列に値を格納しないことを理解することが重要です。たとえば、Employee_Name列にインデックスを作成する場合、これはEmployee_Age列とEmployee_Address列の値もインデックスに格納されないことを意味します。他のすべての列をインデックスに格納しただけの場合は、テーブル全体の別のコピーを作成するのと同じようになり、スペースを取りすぎて非常に非効率になります。
データベースは、インデックスを使用するタイミングをどのようにして知るのですか? 「SELECT * FROM Employee WHERE Employee_Name = 'Abc'」のようなクエリが実行されると、データベースは、クエリ対象の列にインデックスがあるかどうかを確認します。Employee_Name列にインデックスが作成されていると仮定すると、データベースは、インデックスを使用して検索対象の値を見つけることが実際に意味があるかどうかを判断する必要があります。 、テーブル全体をスキャンするだけでより効率的です。
データベースインデックスを作成するコストはどのくらいですか?
スペースを使用します。また、テーブルが大きいほど、インデックスも大きくなります。インデックスのもう1つのパフォーマンスヒットは、対応するテーブルの行を追加、削除、または更新するたびに、同じ操作をインデックスに対して実行する必要があることです。インデックスには、インデックスがカバーするテーブルの列にあるものと同じ分までのデータを含める必要があることに注意してください。
一般的なルールとして、インデックス付けされた列のデータが頻繁にクエリされる場合にのみ、インデックスをテーブルに作成する必要があります。
こちらもご覧ください
CREATE INDEX ... INCLUDE
句を確認します。私の見解では、あなたの回答には一般化が多すぎます。
create index
は他の列は含まれず、なぜ含まれるべきなのか。If we did just store all the other columns in the index, then it would be just like creating another copy of the entire table, which would take up way too much space and would be very inefficient.
。これはインデックスのより一般化されたバージョンです。CREATE INDEX ... INCLUDE
他の列を考慮した新しいバージョンです。私が説明した投稿は、より一般的なバージョンを検討しています。すべてのデータベースを考慮すると、インデックスはどのように機能するでしょうか。だよね?回答は反対票に値すると思いますか?
インデックスは、テーブルの特定の列の値を格納するデータ構造にすぎません。インデックスはテーブルの列に作成されます。
例:私たちは、と呼ばれるデータベーステーブル持っているUser
3つの列とを- Name
、Age
とAddress
。User
テーブルに数千の行があると仮定します。
ここで、クエリを実行して、「John」という名前のユーザーのすべての詳細を検索するとします。次のクエリを実行すると、
SELECT * FROM User
WHERE Name = 'John'
データベースソフトウェアは、文字どおりUser
テーブルのすべての行を調べてName
、その行のが「John」であるかどうかを確認する必要があります。これには時間がかかります。
これはindex
私たちを助ける場所です:インデックスは、調査する必要があるテーブルのレコード/行の数を本質的に削減することにより、検索クエリを高速化するために使用されます。
インデックスを作成する方法:
CREATE INDEX name_index
ON User (Name)
ANは、index
から成る列の値(例:ジョン)のテーブルから、それらの値はに格納されたデータ構造。
したがって、データベースでインデックスが使用され、Johnという名前の従業員が検索されます。これは、おそらくインデックスがユーザー名でアルファベット順にソートされるためです。また、並べ替えられているため、「J」で始まるすべての名前がインデックス内で互いに隣り合うため、名前の検索がはるかに高速になります。
簡単な提案です。インデックス作成には追加の書き込みとストレージスペースがかかるため、アプリケーションで追加の挿入/更新操作が必要な場合は、インデックスなしのテーブルを使用することをお勧めしますが、より多くのデータ取得操作が必要な場合は、インデックス付きのテーブル。
データベースインデックスを本のインデックスと考えてください。
犬についての本があり、たとえばジャーマンシェパードについての情報を知りたい場合は、もちろん本のすべてのページをめくって、探しているものを見つけることができますが、これはもちろん時間がかかるもので、とても早い。
別のオプションは、本の[インデックス]セクションに移動し、探しているエンティティの名前(この例ではジャーマンシェパード)を使用して探しているものを見つけ、ページ番号を確認することです。あなたが探しているものをすぐに見つけてください。
データベースでは、ページ番号は、エンティティが配置されているディスク上のアドレスにデータベースを転送するポインタと呼ばれます。同じジャーマンシェパードの例えを使用すると、次のようなもの( "ジャーマンシェパード"、0x77129)ができ0x77129
ます。ここで、はジャーマンシェパードの行データが格納されているディスク上のアドレスです。
つまり、インデックスは、クエリ検索を高速化するために、テーブルの特定の列の値を格納するデータ構造です。