2010-11-24 4 views
13

ここでは、パフォーマンスの問題の改善策としてインデックスを追加することを推奨します。データベースインデックス:良いこと、悪いこと、時間の無駄ですか?

(私は、&を読むことについてのみ話しています、我々はすべてのインデックスが書き込みを遅くすることができます知っている)。

私はDB2とMSSQLの両方で長年何度もこの救済策を試してきましたが、結果はいつも失望していました。

私の知見は、インデックスがより良いものになるということが明らかであっても、クエリオプティマイザがよりスマートで、巧みに選ばれたインデックスがほとんど常に物事を悪化させたことが判明しました。

私の経験は主に小さなテーブル(< 100,000行)に関連していることを指摘しておきます。

索引付けの選択肢に関する詳細なガイドラインはありますか?

正解は推奨事項のリストになり、何かのように:

  • ネヴァー/常にインデックスより
  • は常にマルチフィールドキー
  • 上のインデックスを考慮しない/決してNNNNレコード未満とテーブル/
  • 決して/常にクラスタ化インデックスを使用
  • 決して/常に単一のテーブル
  • にNNNインデックスよりも絶対に使用しないでください/常にとき[I、約学ぶために死んだいくつかの魔法の条件]インデックスを追加

理想的には、答えはいくつかの参考になる例を示します。

+0

すべてはディスクの速度とメモリのサイズなどによって異なります。 – Gabe

+2

まず、質問を編集してください。 ** **インデックスを追加するだけで、クエリーを高速化し、遅くすることはありません。あなたが尋ねることは、クエリオプティマイザ**がインデックスを使用することを指定することです。実際には自分自身で行うことをオーバーライドします。クエリが遅くなる可能性があります。 –

+3

@Charles Bretana:インデックスを追加するCANオプティマイザが不正なプランを選択するか、または他のインデックスの使用に悪影響を与える場合は、クエリを遅くします。また、インデックスを追加すると、一般に挿入/更新/削除が遅くなります。 – sqlvogel

答えて

16

インデックスは化学療法のようなものです...あまりにも多く、あなたを殺してしまいます...あまりにも少なく、あなたが死ぬ...間違ったやり方で死ぬでしょう。あなたはどれだけ、どれくらいの頻度で、どんな種類のものがあなたを殺さないかを知っていなければなりません。

ハードウェア、プラットフォーム、環境、負荷のすべてが役割を果たします。あなたの質問にお答えします。

はい、時には時々です。

+8

ケモアナロジーを(愛する、Charlie Villanueva)愛していますが、何が起こっても、あなたは非常に気分が悪くなるでしょう」 – MusiGenesis

+0

@MusiGenesis HAHAHAH !!!!はい、本当に80))) – Keng

+3

+1確かに、素敵な類推で、おそらくほとんどの人が望んでいるよりも現実に近い – smirkingman

2
Always use clustered indexes. 

実際、あなたはそれらを助けることはできません。テーブルのデータは、ディスク上に特定の順序で配置されます。パイルなどで保存することはできません。このデータをどのように配置するかを指定する機会があります。なぜそれを燃やす?

新しいレコードを追加するテーブルがあり、そのレコードの値が常に(StackOverflowの質問番号のように)大きくなることがわかっている場合は、クラスタードインデックスを作成してください。新しいデータは中間に挿入されませんが、基本的に比較的安価な操作であるディスク上のファイルに追加されます。

2

基本的にDBがデータを収集していて、生きているインデックスがそのフローで進化しなければなりません。テーブルに本当に良いインデックスがあるかもしれませんが、XXXレコードを超えて成長した後、同じテーブルの同じインデックスは役に立たず、その場合はリファクタリングする必要があります。最適化されているように

と高速DBの唯一の方法はそれをすべての時間を監視し、レコードが入って来て時間をかけて、それをリファクタリングすることである。

私はいくつかの時間前になった実際の生活の例では、いくつかによって制限された超高速クエリました時間範囲(AとBの間にcreated_at)と時間範囲が異なる超低速クエリ。同じクエリ、同じデータベース、同じアプリケーション、時間範囲の違いは1つだけです。

+0

+1の異なるキー範囲=異なるパフォーマンス、良いポイントはどのように分析/修正するのですか? – smirkingman

0

ここでは2つのコンセプトを混乱させるようです。 一般 を指標* を追加する は非常に非常にまれに(ほとんどない)遅くなり、より高速な読取り問合せをすることはできません。索引を追加すると、照会オプティマイザーはそれを強制的に使用することはありません。それはそれが恩恵を受けると思う場合にのみそれを使用し、それらの決定については一般に非常に賢いです。

もちろん、すべてのインデックスがパフォーマンスをさらに傷つけます...しかし、スペクトルの反対側では、読み取り専用のデータベース(毎月配布されるUSPSアドレスデータベースのようなもの)運用上の使用では挿入/更新がないため、追加インデックスの唯一の悪影響は、ディスクスペースの使用量です。

を指定することは、クエリオプティマイザがインデックスを使用して実際に行う処理をオーバーライドすることとはまったく異なります。その結果、クエリが遅くなる可能性があります。

EDIT:過度にリテラルな読者による誤解の可能性を排除するために編集されました。

+1

@Charles Bretana:「クエリーをより速く、遅くすることはできません」私は_completely_に同意しません。それは私が作っているポイントです。インデックスを追加すると、クエリオプティマイザがプランを作成する方法が変更されます(インデックスは強力なヒントと見なされます)。私は同じクエリを観察した(そして時間を計られた)が、インデックスが追加されるとかなり遅くなります。そして、私が尋ねるべきことを示唆することを控えてください。質問の語句は、私が探しているものを知っていることを、感謝しなければなりません。 – smirkingman

+0

@smirkingman、あなたが何が起こっているのかは重要な努力に投資する価値がないほど稀です。あなたの質問の表現は、あなたがインデックス技術を理解していないことを示しています。 "...インデックスは物事を良くするだろう、それはクエリオプティマイザがスマートだったことが判明し、私の巧みに選ばれたインデックスはほとんど常に物事を悪化させた。非常にまれで異常な状況(オプティマイザをオーバーライドしない限り)を除いて、このステートメントは文字通り真実ではありません。それが真実であれば、データベース業界全体の残りの部分はすべて馬鹿であることを意味します。 –

+1

@Charles Bretana申し訳ありませんが、彼らはエッジケースではありません。 _私の経験では、インデックスは常に物事を良くし、私はそうではなく、それは私が疑問に思っているこの神話です。私の質問は、これまでの回答が、腸の感情および/または動詞の学習以外の客観的な正当性を欠いていることに留意すると、より有効です。ああ、そしてBTW、私は1990年代初めからDBMSに取り組んできましたが、あなたが熱い夕食を食べた時よりも多くの夕食をクエリプランに費やしていたでしょう。そうではなく、あなたが本で読んだものより具体的なものであなたの答えをバックアップしてください。 – smirkingman

10

大まかには、主キーと外部キーのインデックスを作成する必要があります。通常、プライマリキーはインデックスとして定義されているだけですが、FKはすべてのデータベースにはありません(SQL Serverには絶対含まれていません)。これらを結合で使用するため、これらを定義するためには一般にパフォーマンスが重要です。

  • 最初のフィールドは 値の範囲を持っている必要があります:句は、彼らは同様にいくつかのことを提供するインデックスの恩恵を受けることができる場所

    は今、あなたはあなたが頻繁に使用するフィールドを持っている場合。ビットフィールドまたはフィールドが の2または3値の場合、ほとんどの場合 はインデックスを使用しません。

  • 第2に、あなたが書いたクエリーは可能でなければなりません。つまり、インデックスを使用するように設計する必要があります。インデックスの候補と思われるものからパフォーマンスの向上が得られないのであれば、おそらくsargableではないクエリがあると思います。たとえば、WHERE Nameのように '%Smith'をwhere句として使用します。最初の文字がわからなければ、オプティマイザは索引を使用できません。

小さなテーブルはインデックスからほとんど恩恵を受けません。オプティマイザがメモリ内のすべてを保持できる場合、オプティマイザはメモリ全体を保持することができます。マルチミリオンレコードテーブルを使用している場合は、インデックスが重要であることがわかります。

索引付けは非常に複雑なことがあります。テーマに興味がある場合は、特定のデータベースのパフォーマンスを調整し、それらについて深くお読みください。

+1

具体的な提案のための+1:範囲/ sargable /小さなテーブル – smirkingman

1

テーブルが結合の対象になることが予想される場合は、そのテーブルにクラスタ化インデックスを作成して、データページを通じて順次結合を実行できるようにすることをお勧めします。クラスタード・インデックスの列は、(一部のDBシステムでは)その表の他のすべての索引に含まれます。これは、索引が表データを参照するために使用する値であるためです。他の索引のサイズが大きくなりすぎないようにするには、クラスタ化索引の列をできるだけ狭くする必要があります。したがって、クラスタ化索引では文字データ型ではなく数字のみを使用することをお薦めします。一般的には、列数が少ないほど列数が少なくなりますが、1列あたり12バイトのintという3つの列は、1行当たり1つのnvarchar(32)列よりもはるかに優れています(行あたり64バイト)。

クラスタ化インデックスが狭い場合、非常に大きなテーブルであっても、いくつかの追加インデックスがパフォーマンスに悪影響を与えてはいけません。

2

インデックスが必要です。インデックスだけでは、データに十分な速さでアクセスできます。

可能な限り短くするには:

  • はあなたが頻繁にのためにフィルタリング(またはグループ化)されている列のインデックスを追加します。 (状態または名前など)
  • likeとsql関数は、DBMSにインデックスを使用させないようにする可能性があります。
  • 多くの異なる値を持つ列にのみインデックスを追加する(たとえばブール値フィールドがない)
  • インデックスは外部キーに追加するのが一般的ですが、必ずしも必要ではありません。
  • 非常に短い表に索引を追加しないでください。
  • パフォーマンスをどのように向上させるべきかわからないときは、索引を追加しないでください。

最後に、クエリを最適化する方法を決定する実行計画を見てください。

単一の重要なクエリに対してのみインデックスを追加します。この場合、問題のクエリに必要なインデックス(マルチカラムインデックス)を正確に追加します。

5

使用されることのないインデックスは、ディスク領域の浪費であり、挿入/更新/削除時間の追加にもなります。クラスタリングインデックスを最初に定義し、次にWHERE句を書くときには 追加インデックスを定義するのが最善でしょう。

一般的なインデックス間違いの1つは、インデックスがcol1 ASC, col2 ASC, col3 ASCと定義されているときにcol2(またはcol3)の選択が長くかかる理由が不思議に思う人々です。複数の列インデックスを使用する場合は、WHERE句でインデックスの最初の列、またはインデックスの1番目と2番目の列などを使用する必要があります。

データにcol2でアクセスする必要がある場合は、col2 ASCと定義されている追加のインデックスが必要です。

小さなドメインテーブルでは、インデックスを使用してテーブルから行を読み取る場合よりも、テーブルスキャンを行うほうが速いことがあります。これは、データベースマシンの速度とネットワークの速度によって異なります。

+0

+1一般的なミスを特定し、解決策を提案する – smirkingman

関連する問題