web-dev-qa-db-ja.com

一般に、どの列が適切なインデックスを作成しますか?

インデックスとは何か、データベース内のクエリを最適化するためにそれらをどのように使用できますか? MS SQLデータベース専用ですか?

いくつかのグーグルを読んだ後、私が読んだすべてのものは、一般的に増加し、ユニークな列が良いインデックス(MySQLのauto_incrementのようなもの)を作ることを示唆しています、私はこれを理解していますが、私はMS SQLを使用していて、主キーにGUIDを使用しているようですそのインデックスはGUID列...

85
mmattax

インデックスは、クエリの最適化とテーブルからの結果の迅速な検索に重要​​な役割を果たすことができます。したがって、インデックスを作成する列を選択することが最も重要な手順です。インデックス作成を検討できる主な場所は2つあります。WHERE句で参照される列とJOIN句で使用される列です。つまり、特定のレコードを検索するために必要な列に対して、そのような列にインデックスを付ける必要があります。 SELECTクエリが以下のようなインデックスを使用する買い手という名前のテーブルがあるとします:

SELECT
 buyer_id /* no need to index */
FROM buyers
WHERE first_name='Tariq' /* consider to use index */
AND last_name='Iqbal'   /* consider to use index */

「buyer_id」はSELECT部分​​で参照されるため、MySQLはそれを使用して選択した行を制限しません。したがって、インデックスを作成する必要はありません。以下は、上記と少し異なる別の例です。

SELECT
 buyers.buyer_id, /* no need to index */
 country.name    /* no need to index */
FROM buyers LEFT JOIN country
ON buyers.country_id=country.country_id /* consider to use index */
WHERE
 first_name='Tariq' /* consider to use index */
AND
 last_name='Iqbal' /* consider to use index */

上記のクエリfirst_name、last_nameカラムは、WHERE句にあるため、インデックスを作成できます。また、国テーブルの追加フィールドであるcountry_idは、JOIN句に含まれているため、インデックス付けの対象とすることができます。そのため、WHERE句またはJOIN句のすべてのフィールドでインデックス付けを検討できます。

次のリストは、テーブルにインデックスを作成する場合に常に留意すべきいくつかのヒントも示しています。

  • WHERE句およびORDER BY句で必要な列のみにインデックスを付けます。豊富な列にインデックスを付けると、いくつかの欠点が生じます。
  • MySQLの「インデックスプレフィックス」または「マルチカラムインデックス」機能を活用してください。 INDEX(first_name、last_name)などのインデックスを作成する場合、INDEX(first_name)を作成しないでください。ただし、「インデックスプレフィックス」または「マルチカラムインデックス」は、すべての検索ケースで推奨されるわけではありません。
  • NULL値が格納されないように、インデックス付けを検討する列にNOT NULL属性を使用します。
  • --log-long-formatオプションを使用して、インデックスを使用していないクエリを記録します。このようにして、このログファイルを調べ、それに応じてクエリを調整できます。
  • EXPLAINステートメントは、MySQLがクエリを実行する方法を明らかにするのに役立ちます。テーブルを結合する方法と順序を示します。これは、最適化されたクエリの作成方法、および列にインデックスを付ける必要があるかどうかを判断するのに非常に役立ちます。

更新(15 2月23日):

任意のインデックス(良い/悪い)は、挿入と更新の時間を増やします。

インデックス(インデックスの数とタイプ)に応じて、結果が検索されます。インデックスのために検索時間が長くなる場合、それは悪いインデックスです。

どの本でもそうであるように、「インデックスページ」には章の開始ページ、トピックページ番号の開始、サブトピックページの開始があります。インデックスページの説明は多少役立ちますが、より詳細なインデックスを使用すると混乱したり怖がったりする可能性があります。インデックスにもメモリがあります。

インデックスの選択は賢明でなければなりません。すべての列にインデックスが必要なわけではないことに注意してください。

90
Somnath Muluk

一部の人々はここで同様の質問に答えました: どのように良いインデックスが何かを知っていますか?

基本的に、データのクエリ方法によって異なります。クエリに関連するデータセットの小さなサブセットをすばやく識別するインデックスが必要です。日付スタンプでクエリを実行しない場合、インデックスがほとんど一意であっても、インデックスは必要ありません。特定の日付範囲で発生したイベントを取得するだけの場合、間違いなく1つが必要です。ほとんどの場合、性別のインデックスは意味がありませんが、すべての男性に関する統計情報と、個別にすべての女性に関する統計情報を取得するだけであれば、作成する価値があるかもしれません。クエリパターンが何であるかを把握し、どのパラメータにアクセスすると検索スペースが最も狭くなります。これが最良のインデックスです。

また、作成するインデックスの種類も考慮してください。Bツリーはほとんどの場合に有効であり、範囲クエリを許可しますが、ハッシュインデックスを使用すると、ポイントに直接アクセスできます(ただし、範囲は許可しません)。他の種類のインデックスには、他の長所と短所があります。

がんばろう!

18
SquareCog

それはすべて、テーブルについて尋ねるクエリに依存します。列Xに特定の値を持つすべての行を要求する場合、インデックスを使用できない場合は、テーブル全体をスキャンする必要があります。

インデックスは次の場合に役立ちます。

  • 1つまたは複数の列に高度な一意性があります
  • 列の特定の値または値の範囲を頻繁に探す必要があります。

次の場合には役立ちません。

  • テーブル内の行の大きな%(> 10-20%)を選択している
  • 追加スペースの使用は問題です
  • 挿入のパフォーマンスを最大化したい。テーブルのすべてのインデックスは、データが変更されるたびに更新する必要があるため、挿入および更新のパフォーマンスが低下します。

主キー列は一意であり、行の検索によく使用されるため、通常、インデックス付けに適しています。

6
Plasmer

一般的に(私はmssqlを使用しないので、特にコメントすることはできません)、主キーは良いインデックスを作成します。これらは一意であり、値を指定する必要があります。 (また、主キーは非常に優れたインデックスを作成するため、通常は自動的にインデックスが作成されます。)

インデックスは、事実上、バイナリ検索を可能にするためにソートされた列のコピーです(線形検索よりもはるかに高速です)。データベースシステムは、特にデータが単純な数字よりも複雑な場合、検索をさらに高速化するためにさまざまなトリックを使用する場合があります。

私の提案は、最初はインデックスを使用せず、クエリのプロファイルを作成することです。特定のクエリ(たとえば、姓による人の検索など)が非常に頻繁に実行される場合は、関連する属性とプロファイルに対して再度インデックスを作成してみてください。クエリの速度が大幅に向上し、挿入と更新の速度がわずかに低下する場合は、インデックスを保持します。

(あなたの他の質問で言及されたものを繰り返している場合、おologiesびします、私は以前にそれに遭遇していませんでした。)

5
Zooba

テーブルからデータを抽出するために定期的に使用される列には、インデックスを作成する必要があります。

これには、外部キーが含まれます-

select * from tblOrder where status_id=:v_outstanding

説明フィールド-

select * from tblCust where Surname like "O'Brian%"

列は一意である必要はありません。実際、例外を検索するときに、バイナリインデックスから非常に優れたパフォーマンスを得ることができます。

select * from tblOrder where paidYN='N'
4
pappes

A GUID列はインデックス付けの最適な候補ではありません。インデックスは、意味のある順序、つまりソート(整数、日付など)を指定できるデータ型の列に最適です。

列のデータが一般的に増加するかどうかは関係ありません。列にインデックスを作成すると、インデックスは独自のデータ構造を作成します。このデータ構造は、格納された順序を気にせずにテーブル内の実際のアイテムを参照するだけです(非クラスター化インデックス)。次に、たとえば、インデックスデータ構造に対してバイナリ検索を実行して、高速検索を提供できます。

データを物理的に並べ替える「クラスター化インデックス」を作成することもできます。ただし、テーブルごとにこれらのうち1つしか持てませんが、複数の非クラスター化インデックスを持つことができます。

3
Ash

本当にあなたのクエリに依存します。たとえば、ほとんどテーブルに書き込む場合、インデックスを持たないことが最善です。書き込みが遅くなり、使用されなくなります。別のテーブルとの結合に使用している列は、インデックスの適切な候補です。

また、Missing Indexes機能についてもお読みください。データベースに対して使用されている実際のクエリを監視し、どのインデックスがパフォーマンスを改善したかを知ることができます。

3
jwanagel

主キーは常にインデックスである必要があります。 (実際、MS SQLによって自動的にインデックス付けされなかった場合は驚かれます。)SELECTまたはORDERを頻繁にインデックス化する必要もあります。それらの目的は、単一の値の迅速な検索と高速なソートの両方です。

too多くの列のインデックス作成における唯一の本当の危険は、インデックスもすべて更新する必要があるため、大きなテーブルの行への変更が遅くなることです。インデックスを作成する対象がわからない場合は、最も遅いクエリの時間を計り、最も頻繁に使用されている列を調べて、インデックスを作成します。次に、それらがどれほど高速であるかを確認します。

1
Eevee

昇順または降順で順序付けられた数値データ型は、さまざまな理由で適切なインデックスです。まず、数字は一般に文字列(varchar、char、nvarcharなど)よりも評価が高速です。次に、値が順序付けされていない場合、インデックスを更新するために行やページをシャッフルする必要がある場合があります。それは追加のオーバーヘッドです。

SQL Server 2005を使用していて、uniqueidentifiers(guid)を使用するように設定されており、ランダムな性質である必要がない場合は、順次uniqueidentifierタイプを確認してください。

最後に、クラスター化インデックスについて話している場合、物理データの種類について話していることになります。クラスター化インデックスとして文字列を使用している場合、見苦しくなります。

1
Ian Suttle

GUIDを使用している場合は、さらに高速になります。あなたがレコードを持っているとします

  1. 100
  2. 200
  3. 3000
  4. ....

Index(binary search)を持っている場合、O(n) time。あなたはあなたのテーブルにどんなレコードがあるのか​​知らないからです。

0
Milhous

Ol 'の経験則は、WHERE、ORDER BY、GROUP BY句で頻繁に使用される列、または結合で頻繁に使用されると思われる列でした。主キーではなくインデックスを参照していることに注意してください

「バニラっぽい」答えを出すのではなく、データにアクセスする方法に本当に依存します

0
curtisk

最適なインデックスは、テーブルの内容と何を達成しようとしているかによって異なります。

メンバー社会保障番号の主キーを持つメンバーデータベースの例を取り上げます。アプリケーションの略称はこの方法で個人を参照するため、S.S。を選択しますが、メンバーの姓と名を使用する検索機能も作成する必要があります。次に、これらの2つのフィールドにインデックスを作成することをお勧めします。

最初にクエリするデータを見つけてから、インデックスを作成する必要があるデータを決定する必要があります。

0
Joseph