コース一覧
データベース内部構造:インデックス・トランザクション・分散DB
EXPLAIN の読み方

データベース内部構造:インデックス・トランザクション・分散DB

SQLの書き方ではなく、DBMSの内側を学ぶコースです。RDBとNoSQL、正規化、B-tree、トランザクションとMVCC、クエリプランナ、レプリケーションと分散SQLを通して、性能と整合性の判断根拠を身につけます。

1
データベースの基礎
0. データベースとは8分
1. RDB と NoSQL の違い8分
2. データベースの歴史8分
3. エンティティ関係モデル (ER)8分
4. 主キー・外部キー・候補キー8分
2
正規化
0. 正規化とは何か8分
1. 第1正規形8分
2. 第2正規形8分
3. 第3正規形8分
4. 非正規化のトレードオフ8分
3
インデックスと B-tree
0. インデックスの役割8分
1. B-tree の仕組み8分
2. B+tree(実際の DB 実装)8分
3. ハッシュインデックス8分
4. カバリングインデックス8分
4
トランザクションと ACID
0. トランザクションとは8分
1. ACID 特性8分
2. 分離レベル8分
3. MVCC(マルチバージョン同時実行制御)8分
4. デッドロックと回避8分
5
クエリ最適化
0. クエリプランナの役割8分
1. EXPLAIN の読み方8分
2. Nested Loop / Hash / Merge Join8分
3. インデックスチューニング8分
4. 統計情報とカーディナリティ8分
6
スケーリング
0. レプリケーション8分
1. シャーディング8分
2. CAP 定理8分
3. 結果整合性8分
4. NewSQL と分散 SQL8分

データベース内部構造:インデックス・トランザクション・分散DB

01データベースとは
02RDB と NoSQL の違い
03データベースの歴史
04エンティティ関係モデル (ER)
05主キー・外部キー・候補キー
06正規化とは何か
07第1正規形
08第2正規形
09第3正規形
10非正規化のトレードオフ
11インデックスの役割
12B-tree の仕組み
13B+tree(実際の DB 実装)
14ハッシュインデックス
15カバリングインデックス
16トランザクションとは
17ACID 特性
18分離レベル
19MVCC(マルチバージョン同時実行制御)
20デッドロックと回避
21クエリプランナの役割
22EXPLAIN の読み方
23Nested Loop / Hash / Merge Join
24インデックスチューニング
25統計情報とカーディナリティ
26レプリケーション
27シャーディング
28CAP 定理
29結果整合性
30NewSQL と分散 SQL

データベース内部構造:インデックス・トランザクション・分散DB

EXPLAIN の読み方

1 件返すために、200 万行を読んでいた

WHERE email = 'alice@example.com' で 1 件だけ取り出すクエリが 3 秒かかっているとします。返ってくるのは 1 行です。それでも 3 秒かかるのは、その 1 行を見つけるまでにテーブルの全行を読んでいるからです。

これは EXPLAIN を付ければ、直す前に分かります。MySQL の出力は列が多いのですが、最初に見るのは 1 つだけです。

プレーンテキスト

table  type  possible_keys  key   rows      Extra
users  ALL   NULL           NULL  2013422   Using where

type が ALL で、key が NULL。これは「使える索引が見つからなかったので、全行読んで条件に合うものを拾う」という意味です。rows の 2013422 は、そのために読むと見込んでいる行数です。PostgreSQL では同じ状態が Seq Scan on users と表示されます。

一覧、検索、ログインのような画面でこれが出ていたら、まずここを直します。逆に ref や range、Index Scan が出ているなら、遅さの原因は別のところにあります。

索引が「無い」のか「使えない」のか

ALL になる理由は 2 つに分かれます。索引をそもそも作っていないか、作ってあるのに条件の書き方で使えなくなっているかです。

SQL クエリ

WHERE LOWER(email) = 'alice@example.com'

email に索引があっても、これは使われません。索引に並んでいるのは元の値であって、LOWER() を通した後の値ではないからです。プランナは全行に関数を適用してみるしかなくなります。possible_keys が空なら候補すら無かったということなので、この線を疑います。

見込みが外れていないかは、実測と並べれば分かる

EXPLAIN が出すのは見込みです。本当に速くなったかは、実際に走らせて測ります。

プレーンテキスト

EXPLAIN ANALYZE SELECT ... ;

Index Scan using idx_orders_user on orders  (cost=0.43..88.78 rows=8 width=32)
  (actual time=0.012..1.345 rows=7 loops=10)

rows=8 が見込み、actual の側の rows=7 が実測です。loops=10 は、この部分が 10 回繰り返されたという意味で、1 回 1.3 ミリ秒でも 10 回なら 13 ミリ秒かかっています。時間を食っている場所は、1 回の速さではなくこの掛け算で決まります。

なお PostgreSQL の EXPLAIN ANALYZE は本当にクエリを実行します。UPDATE や DELETE に付けると、見るだけのつもりが更新されます。試すならトランザクションで囲んで、最後に巻き戻してください。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • テーブルDB の表 (Excel のシートみたいなもの)
  • MySQL広く使われるオープンソースのRDBMS
  • PostgreSQL機能が豊富なオープンソースのRDBMS
  • 関数処理に名前を付けて再利用できる単位
  • トランザクション「全部成功 or 全部なかったことに」をまとめる単位
生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/05/27·更新 2026/08/26

関連レッスン

  • Nested Loop / Hash / Merge Join

    3 種類の結合アルゴリズムと最適な場面を比較する

  • インデックスチューニング

    効くインデックス・効かないインデックスを見抜く

  • 統計情報とカーディナリティ

    プランナがコストを計算するために使う統計の仕組み

  • レプリケーション

    Primary / Replica 構成での読み取り分散と整合性

分からないところは Tap (AI先生) に質問できます

24 時間いつでも、あなたのレベルに合わせて日本語で答えます。