ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
EXPLAIN の基本
SQL の実行計画 (Execution Plan) は、オプティマイザが「どの索引を使い、どの順でテーブルにアクセスするか」を表したもの。性能チューニングには必須の情報です。
-- 基本
EXPLAIN SELECT * FROM users WHERE email = 'alice@example.com';
-- 出力例
+----+-------------+-------+------+-------------------+----------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+-------------------+----------+---------+------+------+--------------------------+
| 1 | SIMPLE | users | ref | idx_users_email | idx_em.. | 768 | const| 1 | Using where; Using index |
+----+-------------+-------+------+-------------------+----------+---------+------+------+--------------------------+
主要フィールドの意味
| 列 | 意味 | 注目ポイント |
|---|---|---|
id | クエリ内の SELECT 通し番号 | サブクエリ / UNION で複数になる |
select_type | SIMPLE / PRIMARY / SUBQUERY / DERIVED / UNION ... | 派生テーブルが多いと遅い兆候 |
table | 対象テーブル名(alias) | JOIN 順を読む手がかり |
type | アクセス種別(★ 最重要) | ALL は黄信号、const/eq_ref が良 |
possible_keys | 利用候補のインデックス | 空ならインデックス無し |
key | 実際に使われたインデックス | NULL なら全件スキャン |
key_len | 使われたインデックスの長さ | 複合 index でどこまで効くか |
rows | 読むと推定される行数 | 大きいと再考の余地 |
filtered | WHERE 通過率の推定 % | 低いと WHERE で大量フィルタリング |
Extra | 追加情報(Using where 等) | 「Using filesort」「Using temporary」は要注意 |
type の階層(速い順)
| type | 説明 | 速度 |
|---|---|---|
| system | テーブル 1 行のみ | ★★★★★ |
| const | 主キー / UNIQUE 一致で 1 行 | ★★★★★ |
| eq_ref | JOIN 相手から主キー / UNIQUE で 1 行ずつ | ★★★★ |
| ref | 非ユニーク index で複数行 | ★★★ |
| range | index 範囲スキャン (BETWEEN 等) | ★★★ |
| index | index 全スキャン(テーブル全件より速い) | ★★ |
| ALL | テーブル全件スキャン(フルテーブルスキャン) | ★ |
Extra でよく出る警告
| Extra | 意味 | 対処 |
|---|---|---|
| Using where | WHERE で行をフィルタリング | 通常は問題なし |
| Using index | Covering Index(テーブル本体を読まずに済む) | ★ 良い兆候 |
| Using filesort | ORDER BY のために追加のソート | ORDER BY 列にも index、または複合 index 順序を見直し |
| Using temporary | 中間結果のために一時テーブル作成 | GROUP BY / DISTINCT 見直し |
| Using join buffer | JOIN に index 無し | JOIN 条件カラムに index 追加 |
| Range checked for each record | JOIN 中に range アクセスを毎行判定 | JOIN 順や index を見直し |
EXPLAIN FORMAT=JSON
各演算子のcost / 読み取り bytes / 行推定まで詳細表示します。チューニングには必須。
EXPLAIN FORMAT=JSON
SELECT u.id, u.name, o.total
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.email = 'alice@example.com';
-- 出力(抜粋)
{
"query_block": {
"select_id": 1,
"cost_info": { "query_cost": "2.85" },
"nested_loop": [
{
"table": {
"table_name": "u",
"access_type": "ref",
"key": "idx_users_email",
"rows_examined_per_scan": 1,
"rows_produced_per_join": 1,
"filtered": "100.00",
"cost_info": { "read_cost": "0.25", "eval_cost": "0.10" }
}
},
{ "table": { "table_name": "o", "access_type": "ref", ... } }
]
}
}
EXPLAIN ANALYZE (MySQL 8.0.18+)
実際にクエリを実行して、推定値ではなく実測の時間と行数を返します。推定と実測の乖離を発見するのに有用。
EXPLAIN ANALYZE
SELECT * FROM orders WHERE user_id = 100 ORDER BY created_at DESC LIMIT 10;
-- 出力例
-> Limit: 10 row(s) (cost=4.20 rows=10) (actual time=0.124..0.142 rows=10 loops=1)
-> Sort: orders.created_at DESC, limit input to 10 rows per chunk
-> Index lookup on orders using idx_user_id (user_id=100)
(cost=4.20 rows=42) (actual time=0.050..0.110 rows=42 loops=1)
-- ★ cost=4.20 rows=42 が推定
-- ★ actual time=0.050..0.110 rows=42 が実測
-- 推定と実測が大きく違う場合 → 統計が古い (ANALYZE TABLE 必要)
Visual Explain (MySQL Workbench)
MySQL Workbench を使うと、実行計画をカラフルなツリー図で見られます。
- クエリを書く
- 稲妻アイコン横の下三角 → 「Visual Explain」を選択
- 各ノードの色: 緑(高速)→ 黄 → 赤(遅い)
- 赤いノードにマウスオーバー → 詳細とアドバイス表示
SHOW WARNINGS でリライト後のクエリを見る
EXPLAIN SELECT * FROM users WHERE id IN (SELECT user_id FROM orders);
SHOW WARNINGS;
-- → オプティマイザが書き換えた実際のクエリが見える
-- → サブクエリが JOIN に変換されていることが多い
パフォーマンススキーマで統計を取る
-- 全クエリの平均実行時間 TOP 10
SELECT digest_text, count_star, avg_timer_wait/1e9 AS avg_ms
FROM performance_schema.events_statements_summary_by_digest
ORDER BY avg_timer_wait DESC
LIMIT 10;
-- 特定テーブルへのアクセス統計
SELECT object_schema, object_name, count_star, sum_timer_wait/1e9 AS sum_ms
FROM performance_schema.table_io_waits_summary_by_table
WHERE object_schema = DATABASE()
ORDER BY sum_timer_wait DESC;
PostgreSQL の EXPLAIN との比較
-- PostgreSQL
EXPLAIN SELECT * FROM users WHERE email = 'alice@example.com';
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'alice@example.com';
EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) SELECT ...;
-- BUFFERS の例
-> Index Scan using idx_users_email on users (cost=0.42..8.44 rows=1 width=64)
(actual time=0.025..0.027 rows=1 loops=1)
Index Cond: (email = 'alice@example.com')
Buffers: shared hit=4 ← バッファヒット 4 ブロック
I/O Timings: read=0.000 write=0.000
-- pgAdmin / DataGrip でグラフィカルな実行計画も見られる
典型的な改善パターン
| 症状 | 原因 | 対処 |
|---|---|---|
type=ALL | WHERE 列に index 無し | CREATE INDEX |
Using filesort | ORDER BY が index と不一致 | 複合 index で並び順吸収 |
Using temporary | GROUP BY / DISTINCT が index 外 | GROUP BY 列にも index |
| rows 推定が実測と大きく違う | 統計古い | ANALYZE TABLE |
JOIN で type=ALL | JOIN 条件に index 無し | FK 列に index |
FAQ
Q: 本番の遅いクエリを後追いで EXPLAIN したい
A: スロークエリログ + mysqldumpslow または pt-query-digest で抽出 → EXPLAIN し直し。Performance Schema からも統計取得可。
Q: EXPLAIN と実際の実行で計画が変わる?
A: 統計情報が古い、サーバ負荷、バインド変数の値などで変わることがあります。本番環境で EXPLAIN ANALYZE を直接打つのが確実(読み取りクエリのみ)。
Q: UPDATE や DELETE も EXPLAIN できる?
A: MySQL 5.6+ で可能。EXPLAIN UPDATE / DELETE / INSERT で実行計画が出ます。実際には更新されません(EXPLAIN ANALYZE は実行するので注意)。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページはありません
- ダウンロード&インストール方法(Windows)
- インストール方法(Linux)
- コマンド一覧
- SQL
- データ型
- 関数
- 管理ツール
- 設定
- パフォーマンスチューニング関連
- エクスポートおよびインポート
- エラー&トラブル
- 文字コードの確認
- 実行中の SQL の状態確認およびプロセスキルの方法
- パスワードの無効化設定
- root ユーザーの初期パスワード確認方法
- rootユーザーのパスワード変更方法
- LIMIT, OFFSET の始まりと挙動
- mysqlのバージョン確認方法
- MySQLで実行計画を表示する方法
- レプリケーションのステータス確認方法
- 中央値の導き方(バージョン8未満)
- 階層SQL(バージョン8未満)
- パーセンタイルの導き方
- 特定スキーマの全テーブルの全カラム情報を取得する方法
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- IPv6とは|128bitアドレス・コロン16進表記/::省略・リンクローカル・SLAAC・デュアルスタック NEW 2026-06-22 12:34:44
- MAC アドレスフィルタリングの仕組みと限界 | ネットワーク入門 NEW 2026-06-22 12:19:10
- VPNとは|暗号トンネル・サイト間/リモートアクセス・IPsec/SSL-VPN/WireGuardを解説 NEW 2026-06-22 12:19:10
- WebRTC とは ブラウザ間 P2P の音声・映像・データ通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/2 とは 多重化・HPACK・バイナリフレーム | ネットワーク入門 NEW 2026-06-22 12:17:25
- Web通信プロトコル入門 HTTP/2・HTTP/3・WebSocket・gRPC・WebRTC | ネットワーク入門 NEW 2026-06-22 12:17:25
- gRPC とは HTTP/2 + Protocol Buffers の高速 RPC | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/3 (QUIC) とは UDP ベースの低遅延 Web 通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- WebSocket とは 全二重リアルタイム通信 ws/wss | ネットワーク入門 NEW 2026-06-22 12:17:25
- 証明書と認証局(CA)とは|X.509・信頼チェーン・DV/OV/EV・失効(CRL/OCSP)を解説 NEW 2026-06-22 12:17:24
- ファイアウォールとは|パケットフィルタ・ステートフル・DMZ・次世代FW(L4/L7)を解説 NEW 2026-06-22 12:17:24
- iptables/nftablesとは|テーブル・チェーン・ルール例・永続化をLinux視点で解説 NEW 2026-06-22 12:17:24
- HAProxy とは frontend/backend と設定例 | ネットワーク入門 NEW 2026-06-22 12:17:24
- CDN とは エッジキャッシュ・TTL・Cloudflare/CloudFront | ネットワーク入門 NEW 2026-06-22 12:17:24
- TLS/SSLの仕組み|ハンドシェイク・暗号スイート・前方秘匿性・証明書検証をわかりやすく解説 NEW 2026-06-22 12:17:24
コメントを削除してもよろしいでしょうか?