0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

EXPLAINチートシート

0
Posted at

type — アクセス方法(上ほど効率的)

type 意味
const PKまたはユニークインデックスで1行だけ取得。最速 WHERE id = 1
eq_ref JOINで内部表に毎回1行だけマッチ。constの次に速い JOIN時にPKで結合
ref 非ユニークインデックスで複数行にマッチ WHERE country_code = 'JPN'
range インデックスを使った範囲スキャン WHERE id BETWEEN 10 AND 20
index インデックス全体のスキャン(行本体へのアクセスなし) カバリングインデックス時によく出る
ALL フルテーブルスキャン。インデックスなしか使われていない 要改善のサイン

Extra — 補足情報

Extra 意味 危険度
Using index カバリングインデックス。行本体へのアクセスなし。効率的 ✅ 良い
Using where 行フェッチ後にWHERE条件でフィルタ。普通 普通
Using index condition インデックスアクセス+行本体フェッチが発生 普通
Using temporary 内部テンポラリテーブルが発生。GROUP BY / Window関数 ⚠️ 注意
Using filesort 追加ソートが発生。ORDER BYのインデックスなし ⚠️ 注意
Using temporary + Using filesort 両方発生。重い処理のサイン。インデックス追加を検討 🔴 要改善
NULL 特記事項なし 普通

主要カラムの意味

カラム 意味
rows フェッチする見積もり行数。少ないほど良い
filtered rowsのうちWHERE条件で残る割合(%)。インデックスやヒストグラムがないカラムでは固定値(= なら10.00)
key 実際に選ばれたインデックス。NULLならインデックス未使用
possible_keys 使える候補インデックス。keyと違う場合は意図と異なるインデックスが選ばれている可能性あり

select_type の値

select_type 意味
SIMPLE サブクエリなしの単純なSELECT
PRIMARY 一番外側のクエリ
DERIVED FROM句サブクエリ(派生テーブル)
DEPENDENT SUBQUERY 相関サブクエリ(N+1のサイン)

EXPLAIN ANALYZE — 実測値の読み方

-> Filter: (country.Continent = 'Asia')
     (cost=25.7 rows=34.1) (actual time=0.176..0.592 rows=51 loops=1)
      ↑見積もりコスト ↑見積もり行数   ↑最初の行まで  ↑全行まで ↑実測行数
項目 意味
cost オプティマイザの見積もりコスト
rows(costの後) 見積もり行数
actual time=A..B 最初の行を返すまでAms、全行返すまでBms
rows(actual timeの後) 実測行数
loops そのステップが何回実行されたか

見積もりと実測のズレが大きい箇所 → ヒストグラム追加(ANALYZE TABLE t UPDATE HISTOGRAM ON col)を検討


JOINの実行計画(NLJ)

状況 読み方
id が同じ 上が駆動表、下が内部表。駆動表の行数 = ループ回数
id が違う id が大きい方が先に処理される
select_type: DERIVED FROM句サブクエリ。id が大きい方が先に処理された派生テーブル

遅いクエリを見たときのチェックリスト

チェック 症状 対処
type: ALL インデックスがない or 使われていない → インデックス追加を検討
Extra: Using temporary GROUP BYのカラムにインデックスなし → インデックス追加またはクエリ見直し
filtered が低い(10.00など固定値) オプティマイザの見積もりが不正確 → ヒストグラム追加
select_type: DEPENDENT SUBQUERY 相関サブクエリ(N+1)→ JOINまたはWITH句に書き直し
rows が多い フェッチ行数が多い → 複合インデックスやカバリングインデックスを検討

よく使うコマンド

-- 実行計画を確認
EXPLAIN SELECT ...;

-- 実測値も確認(実際に実行される)
EXPLAIN ANALYZE SELECT ...;

-- ヒストグラムを追加してfilteredの精度を改善
ANALYZE TABLE city UPDATE HISTOGRAM ON Name;

-- ヒストグラムを削除
ANALYZE TABLE city DROP HISTOGRAM ON Name;

-- 実際に何行読んだか確認
FLUSH STATUS;
-- クエリを実行
SHOW SESSION STATUS LIKE 'Handler_read%';

-- ロック状況を確認
SELECT object_name, index_name, lock_type, lock_mode, COUNT(*) AS locked_rows
FROM performance_schema.data_locks
WHERE lock_type = 'RECORD'
GROUP BY object_name, index_name, lock_type, lock_mode;

-- デッドロックの詳細を確認
SHOW ENGINE INNODB STATUS\G

lock_mode の読み方

lock_mode 意味
X ネクストキーロック(レコード+手前のギャップ)。REPEATABLE-READで発生
X,REC_NOT_GAP ギャップなし排他ロック(その行だけ)。READ-COMMITTEDや=検索で発生
X,GAP ギャップのみのロック
S 共有ロック(FOR SHARE)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?