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

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

入れたばかりのテーブルで、クエリが返ってこない

移行作業で新しいテーブルを作り、500 万行を流し込み、動作確認のクエリを 1 本投げた。返ってきません。索引はちゃんと作ってあります。

原因は、DB がまだそのテーブルを「ほぼ空」だと思っていることです。プランナは実行のたびに行を数えているわけではありません。別に持っている記録、統計情報を見て見積もっています。作った直後の記録は 0 行に近い値のままなので、「どうせ数行だから 1 行ずつ相手を探しに行けばよい」という手順を選びます。実際には 500 万行あるので、それが延々と続きます。

大量に入れた直後に ANALYZE(MySQL では ANALYZE TABLE)を打つ習慣は、このためにあります。

プランナは数えていない、見積もっている

WHERE age > 30 AND country = 'JP' が何行返すかを、プランナは次のように計算します。

  1. テーブルの総行数を記録から取る(100 万行)
  2. country = 'JP' を満たす割合を推定する(0.3)
  3. age > 30 を満たす割合を推定する(0.5)
  4. 掛け合わせる(100 万 × 0.3 × 0.5 = 15 万行)

2 と 3 の割合を出すのに使うのが、列ごとの値の散らばり方の記録です。異なる値がいくつあるか(カーディナリティ)、どの範囲にどれだけ集まっているか(ヒストグラム)が入っています。

列異なる値の数1 つの値で絞ったときの見込み
email100 万ほぼ 1 行
age1001 万行
is_deleted250 万行

異なる値が多い列ほど、1 つ指定したときに残る行が少なくなります。索引が効く列と効かない列の差は、ここから来ています。

4 の掛け算には、注意すべき仮定が 1 つあります。2 つの条件が互いに無関係だと見なしていることです。country = 'JP' AND city = 'Tokyo' のように、片方が決まればもう片方もほぼ決まる組み合わせでは、掛けた結果は実際よりずっと小さくなります。

外れていることは、実測と並べれば分かる

見積もりが当たっているかは EXPLAIN ANALYZE で確かめられます。見込みの rows と実測の actual rows を見比べて桁が違っていれば、そのクエリの手順は当てにならない前提で選ばれたことになります。

外れる原因はだいたい 2 つです。統計が古いか、上の無関係という仮定です。前者は ANALYZE で解消します。増減の激しいテーブルは、自動実行の閾値を下げてこまめに取り直す設定にしておきます。後者は、PostgreSQL なら列の組み合わせを登録して、相関ごと記録させることができます。

3 つ目として、抜き出し方の問題もあります。統計は全行を読んで作るわけではなく、一部を抜き出して作られます。ですから、ごく一部の値だけが極端に多いような偏りは、抜き出しから漏れて記録に載らないことがあります。何度 ANALYZE を打っても見積もりが合わないなら、抜き出す量を増やす設定を検討してください。

「索引を貼ったのに遅い」の犯人が、索引ではなく古い統計だったという話は珍しくありません。

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

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

  • テーブルDB の表 (Excel のシートみたいなもの)
  • MySQL広く使われるオープンソースのRDBMS
  • PostgreSQL機能が豊富なオープンソースのRDBMS
生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/05/27·更新 2026/08/26

関連レッスン

  • レプリケーション

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

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

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

  • Nested Loop / Hash / Merge Join

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

  • EXPLAIN の読み方

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

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

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