QUIZ 30分

合格基準

8問中7問正解(80%以上)で合格

これはL2月3「データの要塞を築こう」の卒業試験です。全ステップの内容を総合的に問います。


Q1: 正規化と非正規化

SNSアプリで「投稿のいいね数」をpostsテーブルにlike_countカラムとして持つ設計は、正規化の観点からどう評価されるか?

  • A) 完全な正規化違反であり、絶対に避けるべき
  • B) 意図的な非正規化であり、パフォーマンス上の理由で妥当
  • C) 第一正規形に違反している
  • D) 外部キー制約の違反である
回答と解説

正解: B

like_countは正規化の観点からは冗長(likesテーブルのCOUNTで導出可能)だが、毎回のCOUNT(*)はパフォーマンスに悪影響を与える。SNSのような読み取り頻度の高いシステムでは、意図的な非正規化として妥当な設計判断。


Q2: インデックス設計

以下のクエリに最も効果的なインデックスはどれか?

SELECT * FROM posts
WHERE user_id = 1 AND is_deleted = false
ORDER BY created_at DESC
LIMIT 20;
  • A) CREATE INDEX idx ON posts(created_at DESC)
  • B) CREATE INDEX idx ON posts(user_id, created_at DESC) WHERE is_deleted = false
  • C) CREATE INDEX idx ON posts(is_deleted, user_id)
  • D) CREATE INDEX idx ON posts(created_at DESC, user_id)
回答と解説

正解: B

WHERE条件の user_id を先頭に、ORDER BYの created_at DESC を次に配置した複合インデックス。WHERE is_deleted = false を部分インデックスの条件にすることで、削除済み投稿を含まないコンパクトなインデックスになる。


Q3: NoSQLの選択

リアルタイムランキングシステムで「スコアの追加」「トップNの取得」「特定ユーザーの順位取得」を効率的に行うのに最適なデータストアとデータ構造はどれか?

  • A) MongoDB の Collection
  • B) Redis の Sorted Set
  • C) PostgreSQL の通常テーブル
  • D) Cassandra の Wide Column
回答と解説

正解: B

RedisのSorted Setは、スコア付きの順序付き集合。ZADD(スコア追加:O(log N))、ZREVRANGE(トップN取得:O(log N + M))、ZREVRANK(順位取得:O(log N))がすべて効率的に実行できる。


Q4: トランザクション設計

ECサイトの在庫管理で、同一商品への同時購入要求が頻繁に発生する場合、最も適切な同時実行制御はどれか?

  • A) 楽観的ロック(バージョンチェック)
  • B) 悲観的ロック(SELECT FOR UPDATE)
  • C) ロックなし(最後の書き込みが勝つ)
  • D) テーブルロック
回答と解説

正解: B

在庫管理は「衝突が頻繁」かつ「売り越しを絶対に防ぐ」必要がある。楽観的ロックではリトライが多発し効率が悪い。SELECT FOR UPDATEで行ロックを取得し、在庫確認と更新を直列化するのが最適。テーブルロックは過度に制限が強い。


Q5: 分散トランザクション

マイクロサービス構成で「注文作成 → 在庫確保 → 決済処理」の3ステップを実行する場合、最も適切なパターンはどれか?

  • A) 単一DBトランザクション
  • B) 2PC(Two-Phase Commit)
  • C) Sagaパターン(Orchestration)
  • D) ロックなしで実行
回答と解説

正解: C

マイクロサービスは各サービスが独立したDBを持つため、単一トランザクションは不可。2PCはブロッキングと可用性の問題がある。Saga(Orchestration)でローカルトランザクションを連鎖させ、失敗時は補償トランザクションで巻き戻すのが適切。


Q6: ゼロダウンタイムマイグレーション

カラム名を name から full_name に変更する際、Expand-Contract パターンの Expand フェーズで行うべきことはどれか?

  • A) ALTER TABLE users RENAME COLUMN name TO full_name
  • B) ALTER TABLE users ADD COLUMN full_name VARCHAR(100) を実行し、旧カラムはそのまま残す
  • C) ALTER TABLE users DROP COLUMN name を実行する
  • D) アプリケーションのカラム参照を一括変更する
回答と解説

正解: B

Expand フェーズでは新しい構造(full_name カラム)を追加し、旧構造(name カラム)はそのまま残す。これによりアプリケーションは旧カラムで引き続き動作する。データ移行とアプリ切り替えは次のMigrate フェーズで行い、旧カラム削除はContract フェーズ。


Q7: バックアップとモニタリング

本番データベースの障害発生時、RPO = 5分、RTO = 30分の要件を満たすために最も適切なバックアップ戦略はどれか?

  • A) 日次のフルバックアップのみ
  • B) 週次のフルバックアップ + 日次の差分バックアップ
  • C) 日次のフルバックアップ + WAL連続アーカイブ(PITR対応)
  • D) 月次のフルバックアップのみ
回答と解説

正解: C

RPO 5分を満たすには、5分以内のデータロスに収まるバックアップが必要。WAL連続アーカイブにより、ほぼリアルタイム(WALセグメント単位)の復旧点を確保できる。日次フルバックアップと組み合わせることで、PITRで任意の時点に復旧可能。RTO 30分もPITRなら実現可能。


Q8: 総合設計判断

SNSプラットフォームのタイムライン機能で、フォロー中ユーザーの投稿を時系列で表示する場合、最も効果的なアーキテクチャはどれか?

  • A) 表示時に毎回 JOIN クエリを実行する(Pull モデル)
  • B) 投稿時にフォロワーのタイムラインキャッシュに追加する(Push モデル / Fan-out on Write)
  • C) すべてのデータをMongoDBに格納してクエリする
  • D) すべての投稿を単一テーブルに格納し、インデックスなしで検索する
回答と解説

正解: B

Fan-out on Write(Push モデル)は、投稿時にフォロワーのタイムラインキャッシュ(Redis List等)に投稿IDを追加する方式。タイムライン表示時はキャッシュを読むだけなので高速(200ms以内の要件を満たせる)。Pull モデルでは表示ごとにJOINが必要で、フォロー数が多い場合にパフォーマンスが悪化する。ただし、フォロワー数が非常に多いユーザー(100万人以上)はPull モデルと組み合わせるハイブリッド方式が実用的。


結果

合格(7問以上正解)

おめでとうございます。L2月3「データの要塞を築こう」を修了しました。

あなたは以下のスキルを習得しました:

  • 正規化理論に基づくデータモデリング
  • インデックスとクエリ最適化
  • RDBとNoSQLの使い分け
  • トランザクションとデータ整合性の設計
  • 安全なマイグレーション計画

次は L2 月4 に進みましょう。

不合格(6問以下)

Step 4-5 を復習してから再挑戦してください。特に以下を重点的に:

  • トランザクション設計(ロック戦略、Saga)
  • ゼロダウンタイムマイグレーション
  • バックアップ戦略とモニタリング

推定所要時間: 30分