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万件
※データの作成はこちらを参照
ageが35の条件でselectをしてみる。
平均が0.5 sec
ここでempテーブルのageにindexを作成。
create index idx_age on emp(age);
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_age` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=2490316 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
再実行してみます
0.1 secと実行結果が速くなりました。
実行計画の結果を比較してみます。
indexなし
EXPLAINの結果の各カラムの意味
- id: クエリの各部分に一意の識別子を割り当てます。このクエリは単一のSELECT文であるため、
1
です。 - select_type: クエリのタイプを示します。
SIMPLE
は、サブクエリを含まない単純なSELECT文であることを示します。 - table: クエリの対象となるテーブルを示します。ここでは
emp
テーブルです。 - partitions: 使用されるパーティションを示します。ここでは
NULL
で、パーティションは使用されていないことを示します。 - type: テーブルへのアクセス方法を示します。
ALL
は全行スキャン(フルテーブルスキャン)が行われていることを示します。 - possible_keys: クエリで使用可能なインデックスを示します。ここでは
NULL
で、使用可能なインデックスがないことを示します。 - key: 実際に使用されるインデックスを示します。ここでは
NULL
で、インデックスが使用されていないことを示します。 - key_len: 使用されているインデックスキーの長さを示します。ここでは
NULL
で、インデックスが使用されていないことを示します。 - ref: インデックスのカラムに一致する列を示します。ここでは
NULL
で、インデックスが使用されていないことを示します。 - rows: MySQLがクエリ実行時に検査すると推定する行の数を示します。ここでは
985,251
行です。 - filtered: 条件を満たすと予想される行の割合を示します。ここでは
10.00
で、全行の10%が条件を満たすと予想されます。 - Extra: クエリの追加情報を示します。
Using where
は、WHERE
句によるフィルタリングが行われていることを示します。
解釈
この結果から、次のことがわかります:
- 全行スキャン(フルテーブルスキャン):
- typeが
ALL
であるため、MySQLはemp
テーブルの全行をスキャンしています。これは、適切なインデックスがない場合によく見られる状況です。
- typeが
- インデックスの欠如:
- possible_keysとkeyが
NULL
であるため、このクエリで使用可能なインデックスが存在せず、全行をチェックする必要があります。
- possible_keysとkeyが
- 行数の推定:
- rowsが
985,251
で、これはMySQLがクエリ実行時にスキャンすると推定する行の数です。テーブルの全行をスキャンすることを意味します。
- rowsが
- フィルタリングの効率:
- filteredが
10.00
で、これは全行のうち約10%の行がWHERE
句の条件(age = 35
)を満たすと予想されていることを示します。
- filteredが
- 追加のフィルタリング:
- Extraが
Using where
であるため、MySQLはスキャンした行に対してさらにフィルタリングを行い、age = 35
の条件を適用しています。
- Extraが
indexあり
EXPLAINの結果の各カラムの意味
- id: クエリの各部分に一意の識別子を割り当てます。このクエリは単一のSELECT文であるため、
1
です。 - select_type: クエリのタイプを示します。
SIMPLE
は、サブクエリを含まない単純なSELECT文であることを示します。 - table: クエリの対象となるテーブルを示します。ここでは
emp
テーブルです。 - partitions: 使用されるパーティションを示します。ここでは
NULL
で、パーティションは使用されていないことを示します。 - type: テーブルへのアクセス方法を示します。
ref
はインデックスによる参照が行われていることを示します。 - possible_keys: クエリで使用可能なインデックスを示します。ここでは
idx_age
が表示されています。 - key: 実際に使用されるインデックスを示します。ここでは
idx_age
が使用されています。 - key_len: 使用されているインデックスキーの長さを示します。ここでは
5
で、age
カラムのインデックスの長さです。 - ref: インデックスのカラムに一致する値を示します。ここでは
const
で、定数値(ここではage = 35
)がインデックスに使用されています。 - rows: MySQLがクエリ実行時に検査すると推定する行の数を示します。ここでは
9,654
行です。 - filtered: 条件を満たすと予想される行の割合を示します。ここでは
100.00
で、インデックスによる検索結果すべてが条件を満たすことを示します。 - Extra: クエリの追加情報を示します。
Using index
は、クエリがインデックスカバーされている(インデックスだけでクエリが完了する)ことを示します。
解釈
この結果から、次のことがわかります:
- インデックスの使用:
- typeが
ref
であるため、MySQLはidx_age
インデックスを使用して、age = 35
の条件に一致する行を効率的に検索しています。
- typeが
- 適切なインデックス:
- possible_keysおよびkeyが
idx_age
であるため、このインデックスがクエリに使用されています。適切なインデックスが存在し、使用されていることを示します。
- possible_keysおよびkeyが
- インデックスキーの長さ:
- key_lenが
5
で、これはインデックスキーの長さを示しています。age
カラムのデータ型に基づいてこの長さが決定されます。
- key_lenが
- 参照の種類:
- refが
const
で、定数値(ここではage = 35
)がインデックスに使用されています。
- refが
- 行数の推定:
- rowsが
9,654
で、これはMySQLがインデックスを使用して検索すると推定する行の数です。
- rowsが
- フィルタリングの効率:
- filteredが
100.00
で、インデックスによる検索結果が条件を完全に満たしていることを示します。これは、インデックスが効率的に条件に合致する行を特定できていることを示します。
- filteredが
- 追加のフィルタリングの欠如:
- Extraが
Using index
で、クエリがインデックスカバーされていることを示します。インデックスだけでクエリが完了するため、テーブルの行にアクセスする必要がありません。これによりパフォーマンスが向上します。
- Extraが
まとめ
このEXPLAIN
結果は、emp
テーブルのage
カラムに対するインデックスidx_age
が効果的に使用されていることを示しています。このインデックスにより、MySQLはage = 35
の条件に一致する行を効率的に検索し、全行スキャンを回避しています。その結果、クエリのパフォーマンスが向上し、より迅速な結果が得られます。