emp表 ※indexはなし(primary keyのみ)
CREATE TABLE `emp` (
`id` int NOT NULL AUTO_INCREMENT,
`dept` int DEFAULT NULL,
`age` int DEFAULT NULL,
`sex` int DEFAULT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`bikou` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`birth` date DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2490316 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
レコードは100万件
※データの作成はこちらを参照

dept表 ※indexはなし(primary keyのみ)
CREATE TABLE `dept` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`登録日` date NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
レコードは10件

empテーブルとdeptテーブルを内部結合させる
このとき、empテーブルのdeptにはindexが作られていない。
結果は平均 2 secくらい。

ここでempテーブルのdeptにindexを作成。
create index idx_dept on emp(dept);
CREATE TABLE `emp` (
`id` int NOT NULL AUTO_INCREMENT,
`dept` int DEFAULT NULL,
`age` int DEFAULT NULL,
`sex` int DEFAULT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`bikou` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`birth` date DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_dept` (`dept`)
) ENGINE=InnoDB AUTO_INCREMENT=2490316 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
再実行してみます

平均0.5 secと実行結果が速くなりましたね。
それでは各実行計画を比較してみる
indexなしの場合

EXPLAINの結果の各カラムの意味
- id: クエリの各部分に一意の識別子を割り当てます。このクエリは単一のSELECT文であるため、
1
です。 - select_type: クエリのタイプを示します。
SIMPLE
は、サブクエリを含まない単純なSELECT文であることを示します。 - table: クエリの対象となるテーブルを示します。ここでは
emp
とdept
の両方が表示されています。 - partitions: 使用されるパーティションを示します。ここでは
NULL
で、パーティションは使用されていないことを示します。 - type: テーブルへのアクセス方法を示します。
ALL
は全行スキャン(フルテーブルスキャン)が行われていることを示します(emp
テーブル)。eq_ref
は、結合で使用される主キーの一意インデックスを示します(dept
テーブル)。
- possible_keys: クエリで使用可能なインデックスを示します。ここでは
NULL
またはPRIMARY
が表示されています。 - key: 実際に使用されるインデックスを示します。
NULL
は、emp
テーブルではインデックスが使用されていないことを示します。PRIMARY
は、dept
テーブルで主キーインデックスが使用されていることを示します。
- key_len: 使用されているインデックスキーの長さを示します。
PRIMARY
キーの長さは4バイトです。 - ref: インデックスのカラムに一致する値を示します。
performance.emp.dept
は、dept
テーブルの主キーに対応するemp
テーブルのdept
カラムを示します。 - rows: MySQLがクエリ実行時に検査すると推定する行の数を示します。
emp
テーブルでは985,251
行、dept
テーブルでは1
行です。 - filtered: 条件を満たすと予想される行の割合を示します。ここでは両テーブルとも
100.00%
です。 - Extra: クエリの追加情報を示します。
Using where
は、emp
テーブルに対してWHERE
句によるフィルタリングが行われていることを示します。Using index
は、dept
テーブルに対してインデックスカバーが行われていることを示します。
解釈
この結果から、次のことがわかります:
- 全行スキャン(フルテーブルスキャン):
- typeが
ALL
であるため、emp
テーブルの全行をスキャンしています。適切なインデックスがないため、全行をチェックする必要があります。
- typeが
- インデックス使用の違い:
dept
テーブルでは、typeがeq_ref
で、主キーインデックスが使用されています。これは一意インデックスによる参照であり、効率的な結合が行われています。emp
テーブルではインデックスが使用されていません(keyがNULL
)。
- インデックスの欠如:
- possible_keysが
NULL
であるため、emp
テーブルには使用可能なインデックスがないことがわかります。
- possible_keysが
- 行数の推定:
- rowsが
985,251
で、これはMySQLがemp
テーブルの全行をスキャンすると推定する行の数です。 dept
テーブルでは、結合条件に基づいて1
行のみが関連しています。
- rowsが
- フィルタリングの効率:
- filteredが
100.00
で、emp
テーブルに対してWHERE
句の条件が全行に適用されていることを示します。
- filteredが
- 追加のフィルタリング:
- Extraが
Using where
で、emp
テーブルに対してフィルタリングが行われていることを示します。 dept
テーブルでは、ExtraがUsing index
であり、インデックスを使用して効率的にデータにアクセスしていることを示します。
- Extraが
続いてindexありの場合の実行計画

EXPLAINの結果の各カラムの意味
- id: クエリの各部分に一意の識別子を割り当てます。このクエリは単一のSELECT文であるため、
1
です。 - select_type: クエリのタイプを示します。
SIMPLE
は、サブクエリを含まない単純なSELECT文であることを示します。 - table: クエリの対象となるテーブルを示します。ここでは
dept
とemp
の両方が表示されています。 - partitions: 使用されるパーティションを示します。ここでは
NULL
で、パーティションは使用されていないことを示します。 - type: テーブルへのアクセス方法を示します。
index
はインデックススキャンが行われていることを示します(dept
テーブル)。ref
はインデックスによる参照が行われていることを示します(emp
テーブル)。
- possible_keys: クエリで使用可能なインデックスを示します。ここでは
PRIMARY
とidx_dept
が表示されています。 - key: 実際に使用されるインデックスを示します。
PRIMARY
はdept
テーブルの主キーインデックスを使用し、idx_dept
はemp
テーブルのインデックスを使用しています。 - key_len: 使用されているインデックスキーの長さを示します。
PRIMARY
キーの長さは4バイト、idx_dept
の長さは5バイトです。 - ref: インデックスのカラムに一致する値を示します。
performance.dept.id
はdept
テーブルの主キーに対応するemp
テーブルのdept
カラムを示します。 - rows: MySQLがクエリ実行時に検査すると推定する行の数を示します。
dept
テーブルでは10
行、emp
テーブルでは109,472
行です。 - filtered: 条件を満たすと予想される行の割合を示します。ここでは両テーブルとも
100.00%
です。 - Extra: クエリの追加情報を示します。
Using index
は、クエリがインデックスカバーされている(インデックスだけでクエリが完了する)ことを示します。
解釈
この結果から、次のことがわかります:
- インデックススキャンとインデックス参照:
- typeが
index
であるため、dept
テーブルではインデックススキャンが行われています。これは、インデックスのみを使用してテーブル全体を走査することを示します。 - typeが
ref
であるため、emp
テーブルではインデックスによる参照が行われています。これは、特定の値(ここではdept.id
)に基づいてインデックスが使用されていることを示します。
- typeが
- インデックスの使用:
dept
テーブルではkeyがPRIMARY
であり、主キーインデックスが使用されています。emp
テーブルではkeyがidx_dept
であり、dept
カラムのインデックスが使用されています。
- インデックスキーの長さ:
- key_lenが
PRIMARY
インデックスの長さで4バイト、idx_dept
インデックスの長さで5バイトです。
- key_lenが
- 行数の推定:
- rowsが
10
で、dept
テーブルの全行数が10
であることを示します。 - rowsが
109,472
で、これはMySQLがインデックスを使用して検索すると推定するemp
テーブルの行の数です。
- rowsが
- フィルタリングの効率:
- filteredが
100.00
で、両テーブルのインデックスによる検索結果が条件を完全に満たしていることを示します。
- filteredが
- 追加のフィルタリングの欠如:
- Extraが
Using index
で、クエリがインデックスカバーされていることを示します。インデックスだけでクエリが完了するため、テーブルの行にアクセスする必要がありません。これによりパフォーマンスが向上します。
- Extraが