コース一覧
データベース内部構造:インデックス・トランザクション・分散DB
クエリプランナの役割

データベース内部構造:インデックス・トランザクション・分散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

クエリプランナの役割

遅いクエリは、心当たりでは見つからない

「最近ページが重い」と言われたとき、いちばんやりがちなのは、見た目が複雑なクエリから疑うことです。だいたい外れます。効いているのは、1 回 0.3 秒でも 1 リクエストに 40 回呼ばれている単純な SELECT だったりします。

先に測ります。PostgreSQL なら pg_stat_statements、MySQL ならスロークエリログです。並べる基準は 1 回あたりの時間ではなく、合計時間にします。

SQL クエリ

SELECT calls, total_exec_time, mean_exec_time, query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;

上位 3 本で全体の何割を占めているかを見れば、直す対象はたいてい決まります。ここを飛ばして改善に入ると、速くしたはずなのに体感が変わらない、という結果になります。

同じ SQL が、速かったり遅かったりする

対象が決まったら次は原因ですが、ここで戸惑うのは、SQL に遅くなる要素が書かれていないことです。

SELECT * FROM orders WHERE user_id = 100 ORDER BY created_at LIMIT 10 が指定しているのは、欲しい結果だけです。どの索引を使うか、どこで並べ替えるか、どのテーブルから読み始めるかは 1 文字も書かれていません。それを決めるのがクエリプランナで、同じ SQL でも次のような複数の手順が候補になります。

  • user_id で絞ってから、集めた行をメモリ上で並べ替える
  • created_at の順に読みながら user_id が 100 の行を拾い、10 件たまったら止める
  • (user_id, created_at) の索引を使い、絞り込みと並べ替えを同時に済ませる

どれが速いかは、user_id = 100 の行が 3 件なのか 30 万件なのかで変わります。プランナはテーブルの行数や値の散らばり方の記録からそれを見積もり、いちばん安く済みそうな手順を選びます。

だから、テーブルが育った日を境に、昨日まで速かったクエリが急に遅くなることがあります。SQL は 1 文字も変わっていなくても、選ばれた手順が変わったからです。

選ばれた手順を見るまでは、直しようがない

見積もりが当たっている保証はありません。記録が古ければ外れますし、country と city のように片方が決まればもう片方もほぼ決まる列の組み合わせでも外れます。

ですから、遅い理由を推測で決めないことです。EXPLAIN を頭に付けて実行すると、プランナが選んだ手順が表示されます。

SQL クエリ

EXPLAIN SELECT * FROM orders WHERE user_id = 100 ORDER BY created_at LIMIT 10;

索引を足すのも、SQL を書き換えるのも、この出力を見てからです。手を入れた後にもう一度同じ出力を取れば、狙いどおり手順が変わったのかまで確認できます。

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

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

  • リクエストWeb 通信の基本単位、ブラウザの問い合わせとサーバーの返答
  • PostgreSQL機能が豊富なオープンソースのRDBMS
  • MySQL広く使われるオープンソースのRDBMS
  • SQLデータベースを操作するための共通言語
  • テーブルDB の表 (Excel のシートみたいなもの)
  • メモリプログラムとデータを一時保持する高速領域
生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/05/27·更新 2026/08/26

関連レッスン

  • EXPLAIN の読み方

    MySQL / PostgreSQL の実行計画出力を実例で読み解く

  • Nested Loop / Hash / Merge Join

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

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

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

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

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

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

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