200 行で SQL を覚え、
3,200 万行でデータベースを理解する
第一部はある小さなオンラインショップのデータ(顧客 10 人、注文明細 200 行)で、SQL とデータベースの考え方を手を動かして身につける。 第二部は同じスキーマが 3,200 万行になった世界で、なぜ速いか・なぜ遅いかを実行計画で確かめる。
どのラボも書き換えて実行できる。壊しても npm run seed:basics /npm run seed で作り直せる。
まず 1 回、叩いてみる
見る場所: 結果の表。10 人の顧客
第一部 DB 基礎編
小さなオンラインショップの 200 行のデータを通じて、表計算との違いや SQL・リレーショナルデータベースの基礎を身につけます。
- 00 · 15 分無料データベースとは何か表計算シートの見た目から出発し、「文字列を送ると表が返ってくる」データベースの基本的な仕組みを理解します。
- 01 · 25 分無料テーブルを読む、作る顧客一覧テーブルを操作しながら、行・列・主キー・データ型・NULL の役割を学び、実際にテーブルを作成してデータを投入します。
- 02 · 30 分無料欲しい行だけ取り出す「未発送の注文を新しい順に 10 件取得する」。WHERE、ORDER BY、LIMIT の基本と、NULL がもたらす三値論理の落とし穴を体験します。
- 03 · 25 分無料数える、合計する、束ねる「今月の売上は?」「顧客ごとの注文数は?」。集計関数と GROUP BY の使い方、そして注文のない顧客が集計から消えてしまう問題を解決します。
- 04 · 35 分無料テーブルをつなぐ注文情報に顧客名を紐付ける。JOIN によってデータが増減する感覚、LEFT JOIN、中間テーブルの役割、そしてなぜテーブルを分けるのかを学びます。
- 05 · 25 分無料データを変えるINSERT、UPDATE、DELETE の基本。WHERE 条件を書き忘れるリスク、実行前に影響行数を見積もる習慣、制約によるデータ保護を体感します。
- 06 · 25 分無料クエリの中にクエリを書くクエリの結果は単一の値にも、リストにも、表にもなります。IN、EXISTS、派生テーブル、WITH 句の使い分けと、NOT IN が持つ罠を解説します。
- 6+ · 20 分 · 補足無料補足: 行を潰さずに集計する集計しながら個別の行を残せるウィンドウ関数。ROW_NUMBER、累計値、前後の行との差分の算出方法を学びます(スキップしても第二部に進めます)。
- 07 · 30 分無料途中を見せない(トランザクション)「注文の作成」と「在庫の減算」をひとつの安全な処理としてまとめる。2つのセッションを動かし、コミット前の変更が他から見えない仕組みを体験します。
- 08 · 25 分無料インデックスの正体SHOW INDEX でインデックスの構造を直接確認し、EXPLAIN を使って「全件スキャン」と「インデックスによる高速検索」の違いを実感します。
- 09 · 30 分無料アプリケーションから使うデータベース接続の仕組み、プレースホルダによる SQL インジェクション対策、ORM が発行する SQL と N+1 問題の正体に迫ります。
第二部 パフォーマンス編
1年後、注文明細が 3,200 万行に達したショップで鳴り響くアラート。現場で起きるリアルな障害を調査しながら、実行計画の読み方とパフォーマンス改善を学びます。
- 00 · 15 分無料1 年後のショップと、この計器盤3,200 万行の注文明細データを前に、4つの計器と4つのタブの役割、実行計画ツリーの見方、キャッシュの影響を把握します。
- 01 · 25 分無料フルスキャンとインデックス — 障害 1: マイページの表示に 4 秒かかる同じ 64 行を取得するのに、なぜ 4 秒と 0.2ms という圧倒的な差が生まれるのか。データページ、B+Tree インデックスの構造から紐解きます。
- 02 · 25 分有料実行計画を読む実行計画のツリーを下から上へと辿る読み方を習得。cost、rows、actual time、loops の意味と、推定と実測のズレから問題箇所を特定します。
- 03 · 25 分有料選択性 — 障害 2: インデックスを追加したらタイムアウトが増えた9割が同じ値を持つ列にインデックスを貼ると、なぜオプティマイザは判断を誤るのか。カーディナリティ、選択性、統計情報とヒストグラムを学びます。
- 04 · 30 分有料複合インデックスとカバリング — 障害 3: 購入履歴の月次集計が遅い「特定顧客の直近 30 日分」を最速で取得するインデックス設計。複合インデックスの列順序の原則と、テーブル本体を読みに行かないカバリングインデックスを体感します。
- 05 · 25 分有料InnoDB の内部構造テーブル本体が主キー順のクラスタインデックスとして格納される仕組み。連番と UUID で 25 倍の性能差が生じる理由やバッファプールの働きを解説します。
- 06 · 25 分有料ソートとページング — 障害 4: 注文一覧の 1,000 ページ目が開かないFilesort が発生する条件とメモリ溢れ、OFFSET による大量スキップの線形コスト、そして高速なキーセットページング(シーク法)への書き換えを学びます。
- 07 · 25 分有料JOIN — 障害 5: 商品別の売上画面が終わらないNested loop と Hash join の動作原理。loops が意味するもの、結合キー双方のインデックスの重要性、結合順序の違いがもたらす劇的な影響を検証します。
- 08 · 25 分有料書き込みの代償と、稼働中のスキーマ変更インデックスを増やすと INSERT や UPDATE はどれほど遅くなるのか。INSTANT / INPLACE アルゴリズムを活用し、サービスを止めずに安全に DDL を実行する手法を学びます。
- 09 · 35 分有料ロック — 障害 6: セール開始直後に注文が失敗する行ロック待機、逆順ロックによるデッドロック、ネクストキーロックとギャップロックの挙動、インデックスのない更新がテーブル全体を止めてしまう怖さを体験します。
- 10 · 30 分有料同時に押し寄せるアクセス(同時実行・リソース飽和)同時接続数の増加とレスポンス遅延(p99 の悪化)、重いバッチが API を巻き込むノイジーネイバー問題、ホットスポット行の対策とスロークエリログの読み方を学びます。