web-dev-qa-db-ja.com

MySQLでは、列Xに一意の値がある場合、UNIQUEインデックスとBツリーインデックスの違いは何ですか

テーブルdataがあると仮定しましょう。

CREATE  TABLE `test`.`data` (
`row_id` INT NOT NULL ,
`data_id` INT NOT NULL ,
PRIMARY KEY (`row_id`) );

ここで、data_idに一意の値があると仮定します。 data_idにB-Treeインデックスを設定することと、UNIQUEインデックスを作成することの間に違い(スペース、パフォーマンス、メモリ)はありますか? (InnoDBがストレージエンジンとして使用され、UNIQUEインデックスがクラスタリングキーとして使用できるため、row_idが不要な場合を除きます)

2
matt

本によると

Understanding MySQL Internals

ページ198は次のように述べています。

  • パラグラフ6:MyISAM Bツリーは、リーフノードと非リーフノード、またはページで構成されます。
  • 段落7:リーフノードと非リーフノードの両方のキー値とデータファイル内のレコード位置へのポインタ。非リーフノードには、子ノードへのポインタが追加で含まれています。

この説明を考えると

  • 一意のインデックスには、より多くの非リーフノードがあります。これは、注文と検索に適したモードになります。
  • 一意でないインデックスは、必要な非リーフノードが少なくなります。これは、範囲スキャン(テーブルとインデックス)を実行するためのモードになります。
  • カバーするインデックス (特定のSELECTクエリに必要なすべての列が含まれます)は、両方の最良と最悪を組み合わせます。これにより、より多くの非リーフノードを必要とする範囲スキャンが可能になり、順序付け/検索が可能になります。追加の利点は、必要なすべての列が存在し、インデックスに含まれている場合に、テーブルデータを読み取る必要がないことです。
  • 過去の投稿で他の側面について触れました MySQLでのBTREEの利点

SPACE

  • 一意のインデックスは、リーフ以外のノードのためにより多くのスペースを占有します。
  • インデックスをカバーするには、一意でないインデックスよりも多くのスペースが必要になりますが、テーブルの実際の行数に近づく可能性のある複数列のインデックスのカーディナリティが高くなります。

パフォーマンス(ヘビーライト環境)

  • SELECTは正確なキーに対して非常に高速です
  • カバーリングインデックスにのみ触れるSELECTは非常に高速です
  • ランダムINSERTは、非リーフノードのローテーション/リバランスのために悪夢になる可能性があります
  • キー値を変更する更新は、非リーフノードのローテーション/リバランスのために悪夢になる可能性があります
  • カーディナリティが高いほど、非リーフノードが多くなり、パフォーマンスが向上します。
  • カーディナリティが低いほど、非リーフノードが少なくなり、パフォーマンスが低下します。
  • インデックスの列が多いほど、カーディナリティの影響が大きくなります

メモリー

ストレージエンジンに依存

  • MyISAM:キーバッファはインデックスページのみをキャッシュします。カバーするインデックスはここであなたの親友です
  • InnoDB:バッファプールは、データページ、インデックスページ、およびインデックスページの変更を保持するのに十分な大きさである必要があります( InnoDBアーキテクチャを参照)主な違いは何ですかInnoDBとMyISAMの間?
3
RolandoMySQLDBA