14

AssetsInnoDBエンジンに次のように定義されたテーブルがあります。

CREATE TABLE Assets (
qid SMALLINT(5) NOT NULL,
sid BIGINT(20) NOT NULL AUTO_INCREMENT,
...
PRIMARY KEY (sid,qid),
KEY sid (sid)
);

私は次のクエリを実行しています:

SELECT COUNT(*) FROM Assets WHERE sid>10000;

私のマシンでは、このクエリは約30秒かかり、テーブルに200万のエントリがあります。ここで、インデックスを使用するようにクエリを変更すると、結果は大きく異なります。

SELECT COUNT(*) FROM Assets USE INDEX(<index>) WHERE sid>10000;
  • NO INDEX:明示的ではありませんUSE INDEX。つまり、最初のSELECTクエリ:30秒
  • KEY sid (sid)1.5秒
  • KEY cid (sid,qid)1.5秒
  • PRIMARYUSE INDEX(PRIMARY)クエリ内で使用しました。:30秒

だからこれらは私の質問です:

  1. これに基づいて、クエリは自動的に主キーをインデックスとして使用すると思いました。それでも、との間には大きな違いがUSE INDEX (cid)ありNO INDEXます。違いは何ですか?また、主キーをインデックスとして明示的に指定するにはどうすればよいですか?

  2. NO INDEX実際に主キーをインデックスとして使用しない場合USE INDEX(PRIMARY)、実行時間が同じになる原因は何NO INDEXですか?

  3. フィルタリングのみを行うクエリとのUSE INDEX(sid)間に(パフォーマンスだけでなく)違いはありますか?USE INDEX(cid)sid

長い投稿は許してください、しかし私はそれを議論に開放させたかったのです。


さて、これが私がこれまでに見つけたものです:

まず、キーの設定は次のいずれかである必要があると言われています:PRIMARY KEY(qid,sid), KEY(sid)またはPRIMARY KEY(sid,qid), KEY(qid)。違いがよくわかりません。もしそうなら、私に知らせてください。

次に、KEY sidsid)は、大きなキーよりもはるかに少ないインデックスページを参照するため、高速になる傾向があります。PRIMARY KEYをインデックスとして使用する場合と適切なKEYを使用する場合(同じフィールドを使用している場合でも)の違いについては、次のように言われています。

主キーは、主キーのフィールドを使用してテーブルデータ全体にインデックスを付けます。これは、PRIMARYKEYとデータが一緒に保存されることを意味します。したがって、PRIMARY KEYを使用するクエリは、テーブルデータ全体を処理する必要があり、インデックスが作成されていても、キャッシュできない大きなテーブルに行き詰まります。

個別のキーを使用すると、行数は同じになる可能性がありますが、はるかに小さいインデックス(指定されたフィールドで構成される)がスキャンされ、より少ない数のディスクブロックにヒットするため、実行速度が大幅に向上します。これが、主キーをインデックスとして使用する場合と使用する場合の違いの理由でもあると思いUSE INDEX(cid)ます。どちらも同じフィールドを持っています。

4

1 に答える 1

1

私の経験から、別のインデックスのサブセットであるインデックスを持つと、物事が遅くなる傾向があります..しかし、インデックスを扱うときは多くのことを考慮する必要があるため、マイレージは異なる場合があります..

たとえば、データを頻繁に読み取り、ほとんど変更しない場合は、多くのインデックスを使用するとさらに役立つ可能性があります。操作に多くの挿入/更新/削除が含まれる場合、インデックスが多すぎるとかなり遅くなる可能性があります。

主キーが (sid, qid) の場合、エンジンがおそらく PK のプレフィックスとして取得できる別のキー (sid) を持つことは適切ではないと思います。qid を活用する場合は、むしろ qid にインデックスを追加したいと思います。つまり、そのフィールドでフィルタリングまたはソートするクエリがある場合、またはそのフィールドにいくつかの JOIN がある場合です。

主キーのフィールドの順序に関して、私は通常、それらがクエリでどのように使用されるかを決定しようとします。すべてのクエリが sid を使用し、一部のクエリが sid と qid の両方を使用する場合は、(sid,qid); を選択します。すべてが qid を使用し、一部のみが sid も使用する場合は、(qid, sid) を選択します。sid または qid のいずれかを使用する場合は、PK (sid、qid) と別のキー (qid) を使用して、両方のフィールドを使用するクエリが PK を使用するようにし、sid のみを使用するクエリでも同じことが起こり、最後にqid のみを使用する場合は、(qid) キーを使用します。

use(primary) が mysql にインデックスを使用しないように強制することについて少し混乱していますが、それはお使いの mysql のバージョンに関連する何か (バグ?) かもしれません..

ここでは、インデックス ヒントに関するいくつかのヒントを見つけることができます: http://dev.mysql.com/doc/refman/5.1/en/index-hints.html

一般に、インデックス ヒントをあまり突っ込まないようにしてください。通常、オプティマイザは適切に機能します。そうでない場合は、おそらくどこかに欠陥があるか、インデックスが十分に選択されていないため、テーブルスキャンの方が高速であると考えられています。

さらに、インデックス統計を更新するためにテーブルの最適化が必要になる場合があります..しかし、InnoDBを使用しているため、おそらくそうではありません...

HTH

于 2012-05-08T00:19:48.947 に答える