116

インデックスについて学習しようとしている「インデックスとは何ですか? また、それらを使用してデータベース内のクエリを最適化するにはどうすればよいですか? 」のフォローアップとして、インデックスの候補として適しているのはどの列ですか? 具体的には、MS SQL データベースの場合?

いくつかのグーグルの後、私が読んだことはすべて、一般的に増加し、一意である列が適切なインデックスを作成することを示唆しています(MySQLのauto_incrementなど)。これは理解していますが、MS SQLを使用しており、主キーにGUIDを使用しているため、そのインデックスは GUID 列に利益をもたらしません...

4

12 に答える 12

135

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

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 がクエリを実行する方法を明らかにするのに役立ちます。テーブルがどのように、どの順序で結合されるかを示します。これは、最適化されたクエリを記述する方法や、列にインデックスを付ける必要があるかどうかを判断するのに非常に役立ちます。

更新 (2015 年 2 月 23 日):

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

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

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

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

于 2012-01-20T07:03:40.093 に答える
23

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

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

また、作成するインデックスの種類も考慮してください。B ツリーはほとんどの場合に適していて、範囲クエリを許可しますが、ハッシュ インデックスを使用すると、要点がすぐにわかります (ただし、範囲は許可されません)。他のタイプのインデックスには、別の長所と短所があります。

幸運を!

于 2008-09-20T04:55:00.270 に答える
13

それはすべて、テーブルについてどのようなクエリを実行するかによって異なります。列 X に特定の値を持つすべての行を要求する場合、インデックスを使用できない場合は、完全なテーブル スキャンを実行する必要があります。

索引は、次の場合に役立ちます。

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

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

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

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

于 2008-09-20T05:01:03.530 に答える
7

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

これには以下が含まれます: 外部キー -

select * from tblOrder where status_id=:v_outstanding

説明フィールド -

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

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

select * from tblOrder where paidYN='N'
于 2008-09-20T05:03:17.957 に答える
5

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

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

私の提案は、最初はインデックスを使用せず、クエリをプロファイリングすることです。特定のクエリ (姓で人を検索するなど) が頻繁に実行される場合は、関連する属性とプロファイルのインデックスをもう一度作成してみてください。クエリの速度が著しく向上し、挿入と更新の速度がほとんど低下しない場合は、インデックスを維持します。

(他の質問で言及したことを繰り返している場合はお詫びします。以前に遭遇したことはありません。)

于 2008-09-20T04:49:50.467 に答える
3

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

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

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

于 2008-09-20T04:50:21.327 に答える
3

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

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

于 2008-09-20T04:50:39.267 に答える
2

主キーは常にインデックスにする必要があります。(実際、MS SQL によって自動的にインデックスが作成されなかったとしたら、私は驚くでしょう。) また、自分SELECTまたはORDER頻繁に列にインデックスを作成する必要があります。それらの目的は、単一の値をすばやく検索することと、並べ替えを高速化することの両方です。

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

于 2008-09-20T05:00:34.593 に答える
2

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

SQL Server 2005 を使用していて、uniqueidentifiers (guid) の使用を設定していて、それらをランダムな性質にする必要がない場合は、連続する uniqueidentifier 型を確認してください。

最後に、クラスター化インデックスについて話している場合は、物理データの種類について話していることになります。クラスター化インデックスとして文字列がある場合、それは醜くなる可能性があります。

于 2008-09-20T05:18:08.137 に答える
1

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

「バニラっぽい」答えを出すつもりはありませんが、データへのアクセス方法によって異なります

于 2008-09-20T04:56:15.243 に答える
0

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

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

インデックス (バイナリ検索) がある場合、探しているレコードの物理的な場所を、O(n) 時間で順次検索するのではなく、O( lg n) 時間で見つけることができます。これは、どのレコードがあるかわからないためです。あなたのテーブルで。

于 2008-09-20T04:50:24.633 に答える
0

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

例を取る 会員の社会保障番号の主キーを持つ会員データベース。SS を選択するのは、アプリケーションのプライマリがこのように個人を参照するためですが、メンバーの姓名を利用する検索機能も作成したいからです。次に、これら 2 つのフィールドにインデックスを作成することをお勧めします。

まず、クエリを実行するデータを特定してから、インデックスを作成する必要があるデータを決定する必要があります。

于 2008-09-20T04:59:13.130 に答える