株式会社Good Labでエンジニアをしている コータロー です。
日々、Java・SQL・Gitなどの技術情報や、新人エンジニア向けの学習ノウハウ、
AI活用についての情報を発信しています。
Good Labについて気になった方は、コーポレートサイトもぜひご覧ください。
▶コーポレートサイト
このシリーズについて
「知ってはいる。けど、人に説明しろと言われると詰まる」——そんな歯がゆいDB用語を、1記事1用語・図解中心で解消していくシリーズです。
- 第1回:ACIDの「C(一貫性)」、説明できますか?
- 第2回:トランザクション分離レベル ―「READ COMMITTED」で結局なにが読めるの?
- 第3回:ロックとデッドロック ―「誰が」「何を」「どこまで」ロックしている?
この回だけ、歯がゆさの種類が違います
これまでの3回は「仕組みが分からない」歯がゆさでした。今回は違います。
「スキーマ」は、仕組みが難しいのではありません。同じ単語が、文脈ごとに別のものを指しているだけです。
だから勉強しても腑に落ちません。会話が噛み合わない原因が、自分の理解不足ではなく用語の多義性にあるからです。次の会話に心当たりはありませんか。
- 設計会議で「スキーマ設計から始めよう」
- PostgreSQL担当が「その表は
salesスキーマに置いて」 - MySQL担当が「
CREATE SCHEMAでいいよ、CREATE DATABASEと同じだから」 - NoSQL担当が「うちはスキーマレスなんで」
この4つは、全部ちがう意味です。 整理します。
記事の要:同じ単語・違う対象
先に結論を1枚で。
| 文脈 | 「スキーマ」が指すもの | ざっくり訳すと |
|---|---|---|
| ① 設計論 | DBの構造の記述そのもの(3層モデル) | 設計図 |
| ② PostgreSQL | DB内でテーブルを入れる名前空間 | フォルダ |
| ③ MySQL | データベースそのもの(同義語) | データベース |
| ④ スキーマレス | 「DBが構造を強制しない」の意 | DBが検査しない |
②と③に色を付けました。この2つが同じ単語で正反対に近い意味なので、実務の事故はほぼここで起きます。
① 設計論のスキーマ=「設計図」
もっとも古い意味です。1975年の ANSI/X3/SPARC 報告で提唱された 3層スキーマというモデルがあります。
ポイントは層を分ける目的です。内部スキーマ(物理)を変えても概念スキーマ(論理)が変わらなければ、アプリは影響を受けません。これをデータ独立性と呼びます。
実務では3層すべてを言うより、論理スキーマ(テーブル設計)と物理スキーマ(型・インデックス・格納)の2つで語られることが多いです。「スキーマ設計から始めよう」は、たいていこの意味——つまり**「設計図を描こう」**です。
② PostgreSQLのスキーマ=「フォルダ」
ここから具体物の話になります。PostgreSQLでは、1つのデータベースの中を仕切る名前空間がスキーマです。
同じ名前のテーブルが共存できるのが最大の特徴です。PostgreSQL 16.14(Docker postgres:16) で実測します。
CREATE SCHEMA sales;
CREATE SCHEMA hr;
CREATE TABLE sales.employees (id INT, deal_amount INT);
CREATE TABLE hr.employees (id INT, salary INT);
SELECT table_schema, table_name FROM information_schema.tables
WHERE table_name = 'employees' ORDER BY table_schema;
table_schema | table_name
--------------+------------
hr | employees
sales | employees
(2 rows)
同名の employees が2つ、問題なく共存しました。では SELECT * FROM employees と書いたら、どちらが返るのか。それを決めるのが search_path です。
SET search_path TO sales;
SELECT * FROM employees;
id | deal_amount
----+-------------
1 | 5000
SET search_path TO hr;
SELECT * FROM employees; -- SQL文はまったく同じ
id | salary
----+--------
1 | 300
同一のSQLが、別のテーブルを読んでいます。 列名すら違います。「ローカルでは動いたのに本番で "column does not exist"」という不可解な事故は、これが原因のことがあります。曖昧さを消したいなら sales.employees のように必ず修飾するのが安全です。
そして重要な点。PostgreSQLではスキーマとデータベースは完全に別物です。
DROP DATABASE sales;
ERROR: database "sales" does not exist
sales はスキーマなので、データベースとしては存在しません。
③ MySQLのスキーマ=「データベースそのもの」
MySQLでは話が変わります。公式ドキュメントに、こうはっきり書かれています。
CREATE SCHEMAis a synonym forCREATE DATABASE.
つまり同義語。仕切りではなく、データベースそのものです。MySQL 8.0.46 で実測します。
CREATE SCHEMA shop_a;
SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| demo |
| information_schema |
| mysql |
| performance_schema |
| shop_a |
| sys |
+--------------------+
CREATE SCHEMA で作ったのに、データベース一覧に出てきます。さらに、片方で作って片方で消せます。
CREATE SCHEMA syn_test;
DROP DATABASE syn_test; -- エラーにならない
階層が1段少ないのが分かります。PostgreSQLは「DB > スキーマ > テーブル」の3段、MySQLは「DB(=スキーマ) > テーブル」の2段です。
実害:sales.employees の意味が違う
ここが本記事でいちばん実用的な部分です。まったく同じ文字列が、両者で違うものを指します。
| 書いたSQL | PostgreSQLでの意味 | MySQLでの意味 |
|---|---|---|
sales.employees |
現在のDB内のスキーマ sales のテーブル |
データベース sales のテーブル |
MySQLで実際に CREATE SCHEMA sales; してから demo データベースに接続し、CREATE TABLE sales.employees (id INT); を実行すると、テーブルは demo の中には作られませんでした。
+--------------+------------+
| TABLE_SCHEMA | TABLE_NAME |
+--------------+------------+
| sales | employees |
+--------------+------------+
別のデータベース sales の中に作られています。PostgreSQLの感覚で「demo の中に sales という仕切りを作った」と思っていると、認識がずれたままになります。
④ スキーマレス=「DBが検査しない」だけ
最後の文脈です。「スキーマレスだから設計不要」は、よくある誤解です。
構造がなくなるわけではありません。構造を保証する責任が、DBからアプリへ移るだけです。
第1回で「ACIDのC(一貫性)は、DBが守るのは宣言した制約だけ」と書きました。スキーマレスは、その宣言をゼロにした状態です。守ってくれる人がいないので、アプリのコードが唯一の砦になります。
実際、この負担が重いことは業界も認めていて、MongoDB は後にスキーマバリデーション($jsonSchema で型や必須項目を検査する機能)を用意しました。「スキーマレス」を突き詰めた先で、スキーマが戻ってきているわけです。
正確に言うなら、スキーマレスは「スキーマがない」ではなく 「スキーマが暗黙になっている」。暗黙のスキーマはドキュメントにも残らないので、むしろ厄介という見方もできます。
まとめ:まず「どの文脈?」を確認する
「スキーマは多義語です。設計論なら設計図そのもの、PostgreSQLならDB内でテーブルを仕切るフォルダ、MySQLならデータベースの同義語、スキーマレスならDBが構造を検査しないという意味。特にPostgreSQLとMySQLでは
sales.employeesの指す先が違うので、どちらの話かを最初に確認します」
実務で使える一言はこれです。
「そのスキーマって、PostgreSQLの名前空間の話ですか? それとも設計図の話ですか?」
聞き返すのは理解が浅いからではありません。多義語なので確認が必要なだけです。ここを確認できる人のほうが、むしろ分かっています。
次回
第5回:正規化 ——「第3正規形まで、の『まで』って何?」を図解します。
(シリーズ全11回の予定は第1回に掲載しています)
参考
- PostgreSQL 16 Documentation - Schemas
- PostgreSQL 16 Documentation - CREATE SCHEMA
- PostgreSQL 16 Documentation - Client Connection Defaults(search_path)
- MySQL 8.0 Reference Manual - CREATE DATABASE Statement
- MySQL 8.0 Reference Manual - MySQL Glossary(schema)
- MongoDB Manual - Schema Validation
@kotaro_ai_lab
AI活用や開発効率化について発信しています。フォローお気軽にどうぞ!