コンテンツにスキップ

5-3. 演習問題


1-1. トランザクションの主な目的として最も適切なのはどれか。

  • A. 複数の更新をまとめて安全に扱う
  • B. 文字列を大文字へ変換する
  • C. 画像を圧縮する

1-2. ROLLBACK の役割として最も適切なのはどれか。

  • A. 変更を確定する
  • B. 変更を取り消す
  • C. インデックス名を変更する

1-3. ACID の A として最も適切なのはどれか。

  • A. Atomicity
  • B. Accuracy
  • C. Activity

1-4. インデックスの主な役割として最も適切なのはどれか。

  • A. 検索対象を見つけやすくして読み取りを速くしやすい
  • B. すべての更新を自動で取り消す
  • C. SQL を書かなくても JOIN できるようにする

1-5. インデックスを付けすぎると起こりやすいこととして最も適切なのはどれか。

  • A. 書き込みコストや管理コストが増える
  • B. 主キーが消える
  • C. トランザクションが使えなくなる

1-6. 独立性(Isolation)の説明として最も適切なのはどれか。

  • A. 同時実行の途中結果で他処理が壊れにくいこと
  • B. 文字コードを UTF-8 に固定すること
  • C. すべての列へインデックスを付けること

次の文章の空欄を埋めてください。

  1. まとめて成功 / 失敗を扱う処理単位を (   ) という。
  2. 変更を確定する命令を (   ) という。
  3. 変更を取り消す命令を (   ) という。
  4. ACID の C は (   ) である。
  5. 行を速く見つけるための補助構造を (   ) という。
  6. インデックスが多いと、追加・更新・削除の (   ) が増えやすい。
解答欄

3-1. 銀行振込のような処理でトランザクションが必要な理由を説明してください。

解答欄

3-2. ACID の 4 つの性質が、実務でどのように役立つか説明してください。

解答欄

3-3. インデックスが検索を速くしやすい理由を説明してください。

解答欄

3-4. インデックスを付けすぎると逆効果になりうる理由を説明してください。

解答欄

トランザクションとインデックスの考え方を、ブラウザ上の SQLite で確かめてみましょう。

下のプレイグラウンドは、accountsbooks が入った初期データベースで始まります。
COMMIT / ROLLBACKCREATE INDEX を試したあとは、必要に応じて DBを初期化 を押して最初の状態へ戻してください。

SQLプレイグラウンド
ブラウザ内の SQLite で実行します / SQL は自動保存されます / Ctrl+Enter でも実行できます
結果
「実行」を押すと、ここに実行結果が表示されます。

① COMMIT すると変更が確定することを確かめる

まずはプレイグラウンドの初期 SQL をそのまま実行する。

次の SQL が実行できれば成功:

BEGIN;
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
COMMIT;
SELECT id, owner, balance
FROM accounts
ORDER BY id;

結果は次のようになれば成功:

+----+-------+---------+
| id | owner | balance |
+----+-------+---------+
| 1 | Aoki | 4000 |
| 2 | Ito | 4000 |
+----+-------+---------+

② ROLLBACK に変えると元へ戻ることを確かめる

必要なら先に DBを初期化 を押してから、COMMIT;ROLLBACK; に書き換えてもう一度実行する。

次の SQL が実行できれば成功:

BEGIN;
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
ROLLBACK;
SELECT id, owner, balance
FROM accounts
ORDER BY id;

結果は次のようになれば成功:

+----+-------+---------+
| id | owner | balance |
+----+-------+---------+
| 1 | Aoki | 5000 |
| 2 | Ito | 3000 |
+----+-------+---------+

③ インデックスを作成して登録を確認する

必要なら先に DBを初期化 を押してから、SQL を次の内容へ書き換えて実行する。

CREATE INDEX idx_books_isbn ON books(isbn);
CREATE INDEX idx_books_author_id ON books(author_id);
SELECT name, tbl_name
FROM sqlite_master
WHERE type = 'index' AND tbl_name = 'books'
ORDER BY name;

結果は次のようになれば成功:

+---------------------+----------+
| name | tbl_name |
+---------------------+----------+
| idx_books_author_id | books |
| idx_books_isbn | books |
+---------------------+----------+

④ 代償も確認する

次のように説明できれば成功:

  • 検索は速くなりやすい
  • その代わり、INSERT / UPDATE / DELETE 時はインデックス更新も必要になる
  • だから「よく読む列」に絞って付けるべきである

問題1の解答(クリックで開く)

1-1. 正解:A. 複数の更新をまとめて安全に扱う

解説

  • A が正しい。トランザクションは、複数の更新を 1 つの意味ある処理として扱うための仕組みである。
  • B は誤り。文字列変換とは無関係である。
  • C は誤り。画像圧縮の機能ではない。

トランザクションの本質は「中途半端な成功を残さない」ことである。


1-2. 正解:B. 変更を取り消す

解説

  • B が正しい。ROLLBACK はトランザクション中の変更を取り消す。
  • A の COMMIT が変更確定である。
  • C は誤り。インデックス名変更とは無関係である。

エラー時に安全な状態へ戻すことが、トランザクションの重要な役割である。


1-3. 正解:A. Atomicity

解説

  • A が正しい。Atomicity は「全部成功か全部失敗か」を表す。
  • B と C は ACID の正式な要素ではない。

振込のように途中状態を残したくない処理では、Atomicity が特に重要になる。


1-4. 正解:A. 検索対象を見つけやすくして読み取りを速くしやすい

解説

  • A が正しい。インデックスは目的の行を見つける補助構造である。
  • B は誤り。更新の取り消しはトランザクションの役割である。
  • C は誤り。JOIN の有無とは別問題である。

インデックスは「索引」のようなものであり、探索コストを減らすために使われる。


1-5. 正解:A. 書き込みコストや管理コストが増える

解説

  • A が正しい。インデックスは便利だが、更新時に追加コストがかかる。
  • B は誤り。主キーが消えるわけではない。
  • C は誤り。トランザクションは引き続き使える。

インデックスは「多ければ多いほど良い」ではなく、読み書きのバランスで決める。


1-6. 正解:A. 同時実行の途中結果で他処理が壊れにくいこと

解説

  • A が正しい。Isolation は、同時に動く処理どうしの不正な干渉を減らす性質である。
  • B は誤り。文字コード設定とは関係がない。
  • C は誤り。インデックス数とも無関係である。

独立性は、複数ユーザーが同時に使う実務システムで特に重要になる。

問題2の解答(クリックで開く)
  1. トランザクション

複数の更新をまとめて 1 つの処理単位として扱う考え方である。

  1. COMMIT

ここまでの変更を正式に確定する命令である。

  1. ROLLBACK

ここまでの変更を取り消して、前の安定状態へ戻す命令である。

  1. Consistency

一貫性であり、業務ルールを壊さない性質を表す。

  1. インデックス

行を速く探すための補助構造である。索引と考えると理解しやすい。

  1. コスト

読み取り性能の代わりに、書き込みや管理の負担が増えやすい。

問題3の解答例(クリックで開く)

3-1. 振込でトランザクションが必要な理由

振込は「出金」と「入金」がそろって初めて正しい処理になるからである。 片方だけ成功すると金額が消えたり増えたりして、データが壊れる。 そこで、全部成功したら確定し、途中で失敗したら全体を戻す必要がある。


3-2. ACID が実務で役立つ理由

ACID があると、途中失敗で中途半端なデータを残しにくくなり、ルール違反も減らせる。 さらに複数人が同時に使う状況でも、途中結果の読み合いによる事故を減らしやすい。 つまり ACID は、実務システムの信頼性を支える基本原則である。


3-3. インデックスが検索を速くしやすい理由

インデックスがないと、目的の行を見つけるために全件を見ることがある。 インデックスがあると、対象候補を先に絞りやすくなるため、読む量を減らしやすい。 本の索引と同じで、探す入口を用意するイメージである。


3-4. インデックスを付けすぎる問題

行を追加・更新・削除するたびに、表本体だけでなくインデックス側も更新しなければならない。 そのため読み取りは速くなっても、書き込みが重くなり、管理対象も増える。 よく使う検索列に絞る判断が重要になる。

問題4の解答例(クリックで開く)

① 振込処理の読み方

BEGIN;
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
COMMIT;
SELECT id, owner, balance
FROM accounts
ORDER BY id;

BEGIN から COMMIT までが 1 つの処理単位である。 出金と入金がそろって成功したときだけ確定する、という意味になる。 結果表が 4000 / 4000 になれば、変更が確定したことを確認できる。


② 失敗時の考え方

BEGIN;
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
ROLLBACK;
SELECT id, owner, balance
FROM accounts
ORDER BY id;

ROLLBACK により、トランザクション中の変更は確定せず、処理開始前の状態へ戻る。 そのため結果表は 5000 / 3000 に戻る。 もし直前に COMMIT を試しているなら、先に DBを初期化 してから実行すると分かりやすい。


③ インデックス候補

CREATE INDEX idx_books_isbn ON books(isbn);
CREATE INDEX idx_books_author_id ON books(author_id);
SELECT name, tbl_name
FROM sqlite_master
WHERE type = 'index' AND tbl_name = 'books'
ORDER BY name;

isbn はピンポイント検索、author_id は著者ごとの絞り込みで使いやすい候補である。 sqlite_master を見ると、作成したインデックスが books テーブルへ登録されていることを確認できる。


④ 代償まで含めて考える理由

インデックスは検索を速くしやすいが、更新のたびに維持コストが発生する。 そのため「便利そうだから全部に付ける」ではなく、「どの列をよく読むか」で決めるべきである。 小さなサンプルデータでは速度差が見えにくくても、構造が追加されること自体は playground 上で確認できる。


図で見る

トランザクション: 壊れにくさを守る
インデックス: 見つけやすさを支える

データベース設計では、この 2 つを両立させることが重要である。