2015-09-06 8 views
5

私は外部キーにインデックスを持ち、これらの外部キーを含むインデックスをクラスタ化したテーブルがたくさんあります。例えば、私は次のようなテーブルを持っている:複合インデックスのオーバーヘッド

TABLE: Item 
------------------------ 
id  PRIMARY KEY 
owner FOREIGN KEY 
status 

... many more columns 

MySQLは、主キーと外部キーのインデックスを生成しますが、時には、私は、クラスタ化やカバーのインデックスを作成しますので、クエリのパフォーマンスを向上させたいです。これにより、重複する列を持つ索引が作成されます。私はidx_ownerを落とした場合は、インデックスの最初の列としてownerを持っているので

INDEXES ON: Item 
------------------------ 
idx_owner (owner) 
idx_owner_status (owner, status) 

は、通常idx_ownerを使用することになり、将来のクエリはちょうどidx_owner_statusを使用します。

idx_ownerの価値はありますか? MySQLはインデックスの一部のみを使用していますが、idx_owner_statusを使用するための追加のI/Oオーバーヘッドはありますか?

編集:私は実際に方法に興味がありますInnoDBはインデックスに関して動作します。

答えて

5

短答 短いインデックスを削除します。

ロングAnwser の考慮事項:

がそれをドロップ:

  • INDEXがディスク上に存在する別のB木である、それはスペースをとるようにします。
  • INSERT新しい行またはUPDATEがインデックス付きの列を変更すると、各INDEXが更新されます(遅かれ早かれ)。これには、「バッファーの変更」のためのCPUとI/Oとbuffer_poolスペースが必要です。
  • 任意機能(パフォーマンスとは対照的に)短いインデックスの使用は、より長いインデックスで実行できます。

それを落とさないでください:

  • 長いインデックスが短いものよりもかさばるです。したがって、キャッシュ可能ではありません。したがって、(極端な状況で)より短いものの代わりにより大きなものを使用すると、より多くのI/Oを引き起こす可能性があります。これを悪化させる場合:INDEX(int, varchar255)

最後の項目が実際に他の項目を上書きすることは非常にまれです。 "被覆"

ボーナス

A指数はSELECTで述べ全て列を含むものです。たとえば:

SELECT status FROM tbl WHERE owner = 123; 

そして、これはあなたの両方を置き換える、あなたが本当に速いと、そのクエリが必要な場合は、それによって著しく速く

SELECT status, foo FROM tbl WHERE owner = 123; 

よりさ、INDEX(owner, status)ためだけ B木に触れますインデックスはINDEX(owner, status, foo)です。

PKにおける二次キー

もう一つちらほらは... InnoDBのでは、PRIMARY KEYの列は暗黙のうちにすべての二次キーに追加されます。だから、3つの例はcomposite indexesindex cookbookに本当に私のブログで

INDEX(owner, id) 
INDEX(owner, status, id) 
INDEX(owner, status, foo, id) 

もっと議論です。

関連する問題