0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【DB用語の歯がゆさ 第4回】「スキーマ」って結局なに? ― 同じ単語が文脈で別物を指している

0
Posted at

株式会社Good Labでエンジニアをしている コータロー です。
日々、Java・SQL・Gitなどの技術情報や、新人エンジニア向けの学習ノウハウ、
AI活用についての情報を発信しています。

Good Labについて気になった方は、コーポレートサイトもぜひご覧ください。
コーポレートサイト

このシリーズについて

「知ってはいる。けど、人に説明しろと言われると詰まる」——そんな歯がゆいDB用語を、1記事1用語・図解中心で解消していくシリーズです。

この回だけ、歯がゆさの種類が違います

これまでの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 SCHEMA is a synonym for CREATE 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回に掲載しています)

参考


@kotaro_ai_lab
AI活用や開発効率化について発信しています。フォローお気軽にどうぞ!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?