データベースとSQL 〜なぜ巨大なExcelをみんなで共有すると必ず壊れるのか?〜
1. 素朴な疑問:「Excelでええやん」なぜプロはデータベースを別で作るの?
会社の業務システムやWebサイトを開発するとき、エンジニアは必ず「データベース(MySQLやPostgreSQLなど)」を導入します。 しかし、ITに詳しくない営業担当や企画職の人から見れば、強烈な疑問が湧くはずです。
「データを縦と横の表で管理するだけなら、Excel(エクセル)やGoogleスプレッドシートで十分じゃない? なぜわざわざ難解な専用ソフトを入れて、黒い画面でSQLなんて呪文を打たなきゃいけないの?」
表計算ソフトは直感的で、誰でもセルに入力でき、色も塗れてグラフも出せます。 それに対してデータベースは、画面も素っ気なく、操作するには専門の命令文(SQL)を勉強しなければなりません。一見すると、ただ面倒なだけに見えます。
しかし、もし銀行の預金管理やAmazonの注文システムをExcelで動かしたらどうなるでしょうか? 断言しますが、稼働初日の午前中でデータがめちゃくちゃに破壊され、会社が倒産します。 Excelを愛する人間が想像もつかない「3つの致命的な物理的限界」がそこにあるからです。
2. 概念の芯:巨大Excelが確実に自滅する「3つの物理的欠陥」
Excelが悪いわけではありません。Excelは「1人の人間が手元で計算・分析するための道具」として作られており、「何千人もの人間やプログラムが同時にデータを読み書きする」ようには作られていないのです。
欠陥①:データの重複地獄(正規化されていない)
巨大なExcelシートには、1行ごとに「注文日・顧客名・顧客住所・電話番号・商品名・価格」がずらりと並びます。 田中さんが100回買い物したら、田中さんの住所と電話番号がシートの中に100回も重複して書かれます。
ここで、田中さんが引っ越しをして電話番号が変わったらどうなるでしょうか? 担当者は、シート内にある100箇所の電話番号を、置換機能で一括修正しなければなりません。もし1箇所でも更新し忘れたら、「行によって電話番号が違う」という矛盾(データの不整合)が一生残り続けます。
欠陥②:同時書き込みの衝突(排他制御がない)
共有フォルダにあるExcelを、AさんとBさんが同時に開いて編集したとします。 Aさんが100行目に新しい注文を書き込んで保存し、その1秒後にBさんが保存ボタンを押すと何が起きるでしょうか? Bさんのファイルによって上書きされ、Aさんが苦労して入力した注文データは永久に闇へと消え去ります。
欠陥③:中途半端なクラッシュ(巻き戻せない)
1万行のデータを更新している最中に、パソコンがフリーズしたり停電が起きたりしたら、ファイル自体が破損して二度と開けなくなります。「途中の500行だけ書き換わって、残りの9,500行は昔のまま」という最悪の状態で壊れるのです。
この3大欠陥を力ずくで解決するために生まれたのが、**「RDBMS(リレーショナル・データベース管理システム)」**です。
3. 本題:テーブルをバラバラに切り分けて繋ぐ「正規化とJOIN」
データベースが最初にやる魔法。それは、**「1枚の巨大な表を、綺麗にバラバラの小さな表に切り分けること(正規化)」**です。
データベースは、決して1つの表にすべてを詰め込みません。
- 「顧客テーブル」:田中さんの名前と住所は、世界にたった1行だけ書く。
- 「商品テーブル」:商品の名前と価格も、たった1行だけ書く。
- 「注文テーブル」:「顧客ID: 1 の人が、商品ID: 99 を買った」という番号の組み合わせだけを記録する。
こうしておけば、田中さんが引っ越したとしても、「顧客テーブル」のたった1行の住所を書き換えるだけで作業は終了します。過去100回分の注文履歴の住所も、自動的にすべて最新の正しい住所へと更新されます。
必要なときに合体させる「JOIN(テーブル結合)」
「でも、バラバラにしてしまったら、人間の目には見づらくないですか?」と思いますよね。 その通りです。だから人間やアプリが見るときだけ、SQLという命令文で**「この表とあの表を、ID番号を目印にしてガチャンと合体させて見せてくれ!(JOIN)」**と指示を出します。
裏側の保管庫では「重複ゼロの最小パーツ」に分解して厳重に管理し、画面に出す瞬間だけ「1枚の大きな表」に組み立て直す。これがリレーショナル(関係性)・データベースの真髄です。
4. 奇跡の物理保証:停電しても1円も消えない「ACID特性」
データベースの凄みが最も発揮されるのが、銀行の預金口座のような**「1つのミスも許されないお金の移動」**です。
Aさんの口座から、Bさんの口座へ「1万円を振り込む」という作業を考えてみましょう。 プログラムの中では、必ず2つの作業が順番に行われます。
- Aさんの残高から1万円を引く(10万円 → 9万円)
- Bさんの残高に1万円を足す(5万円 → 6万円)
もし、「1」が終わった直後、「2」を実行する直前の0.001秒の瞬間に、雷が落ちてサーバーの電源がブツンと切れたらどうなるでしょうか?
普通のファイルなら、Aさんの口座から1万円が消え去り、Bさんには届かないまま、世界から1万円が蒸発して大事件になります。
触って試す:送金とロールバックの体験
🏦 振込シミュレータ(Aさん → Bさんへ1万円)
「次へ」で振込の手順を1つずつ進めます。途中で「⚡ ここで障害発生!」を押すと、停電が起きたときにデータベースがどう振る舞うかを体験できます。
合計:150,000円 | 状態:トランザクション開始前
まずは「次へ」を押して、振込を始めてみてください。
これを100%防ぐために、データベースには**「トランザクション(不可分のひとまとまりの処理)」という概念があり、以下の「ACID(アシッド)特性」**という4つの鉄の掟が物理レベルで保証されています。
| 特性の名前 | 小学生でもわかる例え | 実際に保証していること |
|---|---|---|
| A:Atomicity(原子性) | 「全部やるか、全部やらないかの2択」 | 途中でエラーが起きたら、中途半端な状態を許さず、最初から何も起きなかった状態へ完全に巻き戻す(ロールバック)。 |
| C:Consistency(一貫性) | 「ルールの絶対遵守」 | 「残高はマイナスになってはいけない」といった矛盾したデータは、どんなことがあっても絶対に書き込ませない。 |
| I:Isolation(分離性 / 独立性) | 「密室での作業(割り込み禁止)」 | Aさんが計算している途中の引き出し(行)には**「鍵(ロック)」**をかけ、計算が終わるまで他の人には触らせない・覗かせない。 |
| D:Durability(耐久性 / 永続性) | 「石板に刻んだ誓い」 | 一度「完了(コミット)」と返事をしたデータは、その直後にコンセントが引っこ抜かれても、絶対に消えずに残る。 |
どうやって停電に勝つのか?(WAL:ログ先行書き込み)
「コンセントが抜けても消えない(耐久性)」なんて、どうやって実現しているのでしょうか? 実はデータベースは、メモリやハードディスクに本番データを書き込む前に、専用の**「航海日誌(WAL:Write-Ahead Logging)」**という超高速な記録帳に、
- 「今からAから1万引いてBに1万足す作業を始めるぞ」
- 「よし、全部終わったぞ」 という事実だけを猛スピードで先に書き込んでいます。
パソコンが突然落ちても、再起動した瞬間にOSとデータベースがこの日誌を読み返し、 「あ、日誌に『終わった』と書いてあるから本番データに反映しよう(ロールフォワード)」 「あ、日誌の途中で電源が切れてるから、この中途半端な作業は全部なかったことにしよう(ロールバック)」 と自動で復元作業を行います。どんな物理的災害が起きても、絶対にデータの整合性を守り切る要塞。それがデータベースです。
5. 仕組みの種明かし:SQLはなぜ「手順」を書かないのか?
最後に、データベースを操作する言語**「SQL(エスキューエル)」**の正体を暴いておきましょう。
PythonやC言語などの普通のプログラミング言語は、**「手順(手続き)」**を書きます。
- 「まず1行目を開いて、ループで回して、もし名前が山田なら配列に入れて……」
ところが、SQLはまったく違います。手順など1文字も書きません。「欲しい結果(条件)」だけを宣言するのです。
-- 「東京在住で、20歳以上の会員の名前だけを出せ」という命令
SELECT name FROM users WHERE city = 'Tokyo' AND age >= 20;
ここには、「どのファイルをどう開いて、どう検索するか」という手順は一切書かれていません。 なぜこれで動くのでしょうか?
データベースの中には、**「オプティマイザ(最適化エンジン)」という超賢い専属の軍師(AIのような頭脳)**が住んでいます。 人間が「東京の20歳以上をくれ」と条件だけを投げると、軍師が瞬時に計算します。
軍師は、データの件数やインデックス(第8回で学んだ索引)の有無を計算し、何千通りもある検索手順の中から、一番速い最短ルートを勝手に判断して実行してくれます。 人間は「何が欲しいか」だけを言えばよく、「どうやって探すか」は機械が考える。だからこそ、数億件のビッグデータ相手でも人間は迷わずにデータを引き出せるのです。
📝 3行で頭に入る「試験・実務の要点まとめ」
- リレーショナルデータベース(RDBMS)と正規化:データの重複を排除し、テーブル間の矛盾(更新時異状)を防ぐために表を分割する設計を正規化(第1〜第3正規形)と呼ぶ。分割した表は主キー(Primary Key)と外部キー(Foreign Key)を軸にJOINで結合する。
- トランザクションとACID特性:不可分の処理単位。Atomicity(原子性:全実行か全取消か)、Consistency(一貫性:制約の遵守)、Isolation(分離性:他トランザクションからの干渉遮断)、Durability(耐久性:障害時のデータ保証)。
- 排他制御とロック:データの同時更新による不整合を防ぐため、読み込み用の共有ロックと更新用の専有(排他)ロックをかける。互いに相手のロック解除を待って永久に処理が停止する現象をデッドロックと呼ぶ。