MySQL 目次:作成、追加、削除チュートリアル

⚡ スマートサマリー

MySQL インデックスチュートリアルでは、インデックスがデータを高速にソートおよび検索する方法について説明します。インデックスは、1つ以上の列に基づいて作成されるソート済みのルックアップ構造です。CREATE INDEXコマンドでインデックスを追加し、SHOW INDEXESコマンドでインデックスを検査し、書き込み負荷の高いテーブルで読み取り負荷の高いテーブルではDROP INDEXコマンドでインデックスを削除します。

  • 📚 インデックスを辞書のように扱います。 列の値をソートすることで、エンジンはテーブル全体をスキャンすることなく行を特定できます。
  • 🛠️ テーブル上またはテーブル後に作成します: CREATE TABLE文でインデックスをインラインで定義するか、後でCREATE INDEX文を使用して稼働中のテーブルに追加します。
  • 🔍 SHOW INDEXES で検査します。 SHOW INDEXES FROM table_name を使用すると、すべてのインデックス、キー部分、カーディナリティ、および一意性フラグを一覧表示できます。
  • 🧹 書き込みコストが高すぎる場合はドロップします。 インデックスはINSERTとUPDATEの処理速度を低下させるため、使用されていないインデックスをDROP INDEXコマンドで削除して書き込みスループットを回復してください。
  • 🤖 インデックス設計にAIを活用する: AIアシスタントは、低速クエリのログを読み取り、複合インデックスの列順序を提案し、EXPLAINプランを1行ずつ説明します。

MySQL インデックスの概念

何が MySQL 索引?

An index in MySQL インデックスは、列の値を順序付けて格納するデータ構造であり、エンジンが高速に行を検索できるようにします。インデックスは、データのフィルタリングに最も頻繁に使用される列または複数の列に対して作成されます。インデックスは、アルファベット順にソートされたリストのようなものだと考えてください。ソートされていないリストの中から名前を探すよりも、ソートされたリストから名前を探す方がはるかに高速です。

インデックスにはトレードオフがあります。INSERTやUPDATEのたびにインデックスのメンテナンスが必要になるため、書き込み頻度の高いテーブルにインデックスを多く追加すると、全体的なパフォーマンスが低下する可能性があります。一般的に、書き込みよりも読み取り頻度の高いテーブルでは、WHERE、JOIN、ORDER BY句で使用される列にインデックスを作成するのが良いでしょう。

索引を使う理由とは?

動作の遅いシステムは誰にとっても好ましいものではありません。ほぼすべてのデータベースベースのアプリケーションにとって、高いパフォーマンスは最優先事項です。企業はクエリの高速化のためにハードウェアに多額の投資を行っていますが、ハードウェアだけで実現できる性能には限界があります。インデックスの最適化は、より安価で効果的な手段です。

MySQL インデックスの概念

応答時間が遅いのは、通常、行がディスク上に物理的な順序で格納されていることが原因です。インデックスがない場合、 MySQL 述語に一致する行を見つけるには、すべての行をスキャンする必要があります。これは「フルテーブルスキャン」と呼ばれます。インデックスを使用すると、 MySQL 一致する行に直接ジャンプすることで、Bツリー検索のクエリプランがO(n)からおおよそO(log n)に変わります。

構文: インデックスの作成

インデックスは2つの場所で定義できます。

  1. テーブル作成時。
  2. テーブルが既に存在する場合。

例:CREATE TABLE文とインラインでインデックスを作成する

  myflixdb データベースでは、フルネーム列での検索が多数発生すると予想されます。以下のスクリプトは新しい members_indexed インデックス付きのテーブル full_names コラム。

CREATE TABLE `members_indexed` (
    `membership_number` INT(11) NOT NULL AUTO_INCREMENT,
    `full_names`        VARCHAR(150) DEFAULT NULL,
    `gender`            VARCHAR(6)   DEFAULT NULL,
    `date_of_birth`     DATE         DEFAULT NULL,
    `physical_address`  VARCHAR(255) DEFAULT NULL,
    `postal_address`    VARCHAR(255) DEFAULT NULL,
    `contact_number`    VARCHAR(75)  DEFAULT NULL,
    `email`             VARCHAR(255) DEFAULT NULL,
    PRIMARY KEY (`membership_number`),
    INDEX (`full_names`)
) ENGINE = InnoDB;

スクリプトを実行する MySQL 作業台に対して myflixdb データベース。

members_indexed テーブル MySQL ワークベンチ

Refresh myflixdb 新しいものを見る members_indexed テーブル。 ザ・ full_names 列が下に表示されます インデックス ノード。

会員数が増えるにつれて、検索クエリは members_indexed WHEREとORDER BYを使用する full_names 元のクエリよりもはるかに高速です members 索引のないテーブル。

テーブルが既に存在する後にインデックスを追加する

既存のテーブルにインデックスが必要であることはよくあります。検索クエリが遅く、EXPLAIN プランで WHERE 句に含まれる列のフル テーブル スキャンが示されるからです。 CREATE INDEX このステートメントは、テーブルを再作成せずにインデックスを追加します。

CREATE INDEX `id_index` ON `table_name` (`column_name`);

具体的な例 - 検索を高速化する title テーブルの movies テーブル:

CREATE INDEX `title_index` ON `movies` (`title`);

フィルターするすべてのクエリ movies.title は新しいインデックスによってサポートされるようになりました。他の列でフィルタリングを行うクエリは、独自のインデックスがない限り、引き続きテーブルをスキャンします。

注意: クエリで常に同じ組み合わせに基づいてフィルタリングまたはソートを行う場合は、複数の列にまたがる複合インデックスを作成できます。順序が重要であり、先頭の列によってインデックスが使用できるかどうかが決まります。

テーブル上のインデックスを一覧表示する

  SHOW INDEXES テーブルに定義されているすべてのインデックスを表示します。

SHOW INDEXES FROM `table_name`;

例 — リストインデックス movies テーブル:

SHOW INDEXES FROM `movies`;

ステートメントを実行する MySQL ワークベンチ に対して myflixdb 既存のインデックスと、それらがカバーする列を確認する。

注意: 主キーと外部キーは自動的にインデックス化されます MySQL各インデックスには固有の名前があり、それが対象とする列が一覧表示されます。

構文: Drop Index

  DROP INDEX テーブルから既存のインデックスを削除します。これは、書き込み負荷の高いテーブルで、読み取り側で効果を発揮しなくなったインデックスによって速度が低下している場合に役立ちます。

DROP INDEX `index_id` ON `table_name`;

具体的な例 - を落とす full_names インデックスから members_indexed:

DROP INDEX `full_names` ON `members_indexed`;

の種類 MySQL インデックス

MySQL 複数のインデックスタイプをサポートしており、それぞれ異なるワークロードに適しています。

タイプ 目的
主キー 一意の行識別子。InnoDBのテーブルデータとクラスタリングされます。
ユニーク インデックスとして機能しながら、一意性を確保します。
インデックス(Bツリー) 範囲クエリおよび等価性検索に使用されるデフォルトのセカンダリインデックス。
フルテキスト MATCH … AGAINST を使用した自然言語テキスト検索に最適化されています。
空間的な POINTやPOLYGONなどのGISデータタイプ用のRツリーインデックス。
ハッシュ 定数時間で等価性検索を実行します。MEMORYストレージエンジンで使用されます。
複合(複数列) 複数の列を1つのインデックスに結合します。左端が先頭となるルールに従います。

のベスト プラクティス MySQL インデックス

以下の習慣を実践することで、インデックスは有用なものとなり、単なる重荷になるのを防ぐことができます。

  • クエリパターンに対するインデックスであり、列名に対するインデックスではありません。 実際のWHERE、JOIN、ORDER BY句に一致するインデックスを追加するのであって、「重要そうに見えるすべての列」を追加するのではありません。
  • 複合指数の順序を確認してください。 インデックスを使用するには、先頭の列がクエリに含まれている必要があります。
  • 重複するインデックスを避ける: 複合インデックスの先頭の接頭辞は、その接頭辞に対する単一列の検索を既にカバーしています。
  • EXPLAINで検査する: プランナーが実際に新しいインデックスを選択していることを確認してください。
  • 使用されていないインデックスを削除します。 つかいます sys.schema_unused_indexes in MySQL 5.7以降では、何も読み取られないインデックスを検出できます。
  • データ型を一致させる: WHERE句でVARCHAR型の列を数値と比較する場合、暗黙的な型変換が行われるため、インデックスは使用できません。

よくあるご質問

主キーは各行を一意に識別し、常にインデックスが作成されます。汎用インデックスは検索速度を向上させますが、重複する値を許容します。すべての主キーはインデックスですが、すべてのインデックスが主キーであるとは限りません。

非常に小さなテーブル、一意の値が非常に少ない列(カーディナリティが低い)、および読み取りよりも書き込みの頻度がはるかに高いテーブルには、インデックスを作成しないようにしてください。インデックスを追加するたびに、INSERT、UPDATE、DELETE のすべてが遅くなります。

複合(複数列)インデックスは、1つのインデックスで複数の列をカバーします。左端プレフィックスルールに従うため、最初の列、最初の2つの列などに基づいてフィルタリングするクエリには対応できますが、2番目の列のみに基づいてフィルタリングするクエリには対応できません。

ラン EXPLAIN SELECT文の前に。 key この列はオプティマイザが選択したインデックスを示し、 type (NAIST) と 行 アクセス経路が効率的かどうかを教えてくれます。

カバリングインデックスにはクエリに必要なすべての列が含まれているため、エンジンはテーブルを読み込むことなくインデックスのみからクエリに応答します。この場合、EXPLAINは「インデックスを使用しています」と報告します。

一般的な理由としては、ping 関数内の列(WHERE YEAR(col) = …)、暗黙の型キャスト、非常に低いカーディナリティ、古い統計情報。 ANALYZE TABLE 統計情報を更新して検査する EXPLAIN 本当の理由です。

AIアシスタントは、低速クエリのログを取り込み、最も負荷の高いパターンを分類し、単一列インデックスまたは複合インデックスを提案し、EXPLAINプランを分かりやすい英語で説明します。これにより、日常的なワークロードのチューニング時間を数時間から数分に短縮できます。

はい。AIツールは、「メールアドレスと登録日による顧客検索を高速化する」といった要望を、実際に機能するCREATE INDEXステートメントに変換し、列の順序を推奨し、読み書きスループットへの影響を説明します。