3NFまでの正規化
第1、第2、第3正規形と、それによって解消される異常を学びます。
「3NFまでの正規化」はCoddyKit上の無料Coding Interview Prepレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはCoding Interview Prep学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Coding Interview Prepコースには全4レッスンが含まれています。
面接官が正規化について尋ねる理由
正規化はデータベースモデリングの基本であり、面接官は設計レベルでのデータ整合性を理解しているかどうかを確認するために、このテーマを取り上げます。質問はよく次のような形で出されます。「正規化とは何ですか。また、なぜ重要なのですか」
正規化とは、冗長性を減らし、更新・挿入・削除時の異常を防ぐために、列とテーブルを整理するプロセスです。それぞれの正規形(1NF、2NF、3NF)で、より厳しいルールが追加されます。
優れた回答では、教科書的な定義だけでなく、正規化によって取り除かれる異常も挙げます。
3つの異常
正規形を学ぶ前に、正規形で解決する問題を理解しましょう。すべての情報を1か所に格納するような、設計の悪いテーブルでは、次の3つの異常が発生します。
- 更新時異常:同じ事実が複数の行に格納されているため、変更時にすべての行を更新しなければならず、データに不整合が生じます。
- 挿入時異常:関係のないデータも同時に指定しなければ、事実を追加できません(例:注文なしでは商品を追加できない)。
- 削除時異常:1行を削除した結果、別の独立した事実まで誤って消えてしまいます。
サンプルテーブルからこれらの異常を見つけられれば、正規化の各ステップを説明できます。
非正規化された開始時点のテーブル
典型的な面接の例を見てみましょう。注文、顧客、商品を1つの横長のテーブルに混在させています。行をまたいで顧客のメールアドレスと商品の価格が繰り返されていることに注目してください。ここに異常が発生します。
面接では、このテーブルを3NFまで段階的に変換し、それぞれの分割について説明することが求められます。
-- Unnormalized: everything in one table
CREATE TABLE orders_flat (
order_id INT,
customer_id INT,
customer_email VARCHAR(255),
product_id INT,
product_name VARCHAR(100),
unit_price DECIMAL(10,2),
quantity INT
);第1正規形(1NF)
1NFでは、すべての列が単一の原子値を保持し、セル内に繰り返しグループや配列が存在しないことが求められます。
列に'phone1, phone2'のようなカンマ区切りのリストを格納していたり、product1, product2, product3のような列を用意していたりすると、そのテーブルは1NFに違反します。
解決策は、各値をそれぞれ別の行に格納することです。面接官が聞きたいのは、「原子値、繰り返しグループなし、そして各行を識別できるキー」という説明です。
-- Violates 1NF: a list inside one column
-- phones = '555-1111, 555-2222'
-- 1NF fix: one phone per row
CREATE TABLE customer_phone (
customer_id INT,
phone VARCHAR(20),
PRIMARY KEY (customer_id, phone)
);関数従属性
2NFと3NFを説明するには、関数従属性という用語を使う必要があります。A -> Bと書くと「AがBを決定する」という意味になります。つまり、Aの各値に対して、Bの値がちょうど1つ定まるということです。
注文テーブルでは、次のようになります。
customer_id -> customer_emailproduct_id -> product_name, unit_priceorder_id, product_id -> quantity
正規化の本質は、すべての非キー列がキー全体に、そしてキーだけに依存するようにすることです。
第2正規形(2NF)
2NFは、主キーが複合キーの場合に適用されます。非キー列がキーの一部だけに依存すること(部分関数従属)を禁止します。
明細行のキーは(order_id, product_id)です。しかし、product_nameとunit_priceはキー全体ではなくproduct_idだけに依存しています。これは部分関数従属であり、2NF違反です。
解決策は、商品属性をproduct_idをキーとするproductsテーブルに移すことです。
CREATE TABLE products (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
unit_price DECIMAL(10,2)
);
CREATE TABLE order_items (
order_id INT,
product_id INT,
quantity INT,
PRIMARY KEY (order_id, product_id),
FOREIGN KEY (product_id) REFERENCES products(product_id)
);第3正規形(3NF)
3NFでは推移的関数従属を取り除きます。これは、非キー列がキーに直接依存せず、別の非キー列に依存している状態です。
たとえば、ordersテーブルにcustomer_idとcustomer_emailがあるとします。この場合、order_id -> customer_id -> customer_emailとなります。メールアドレスはcustomer_idを経由してのみキーに依存しており、これが推移的関数従属です。
解決策は、顧客を独立したテーブルに分割することです。これで、各テーブルの非キー列は、そのテーブルのキーだけに依存します。
CREATE TABLE customers (
customer_id INT PRIMARY KEY,
customer_email VARCHAR(255)
);
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);一文で覚えるためのフレーズ
面接官は、3NFを一文で要約できる候補者を高く評価します。よく使われる表現は次のとおりです。
「すべての非キー列は、キーに、キー全体に、そしてキーだけに依存しなければなりません」
- キーに -> 1NF(キーがあり、値が原子値である)。
- キー全体に -> 2NF(部分関数従属がない)。
- キーだけに -> 3NF(推移的関数従属がない)。
この一文を覚えておけば、必要なときに3つの正規形をすべて思い出せます。
BCNF:追加で聞かれる質問
鋭い面接官は、3NFよりも厳格なボイス・コッド正規形(BCNF)について尋ねることがあります。
BCNFでは、すべての関数従属性X -> Yについて、Xがスーパーキーであることを求めます。3NFでは、従属する属性が候補キーの一部である場合に、まれな例外が認められます。BCNFでは、その例外さえ取り除かれます。
実務でBCNF違反を目にすることは多くありませんが、BCNFを挙げて、「BCNFは、素属性に関する例外をなくした3NFです」と説明できれば、深い理解を示せます。
正規化しない場合
シニアレベルの回答では、トレードオフにも触れます。正規化によって整合性は向上しますが、クエリの実行により多くの結合が必要になるため、読み取り性能が低下することがあります。
次のような場合は、意図的な非正規化が許容されます。
- 読み取り中心のワークロードで、結合がボトルネックになっている。
- 分析・レポート用のレイヤーを構築している(後で扱うスター・スキーマなど)。
- 冗長なコピーを同期した状態に保てる(トリガー、ETL、マテリアライズドビューなど)。
次のように答えましょう。「OLTPでは整合性のために正規化し、OLAPでは読み取り速度のために意図的に非正規化します」
ホワイトボードでの進め方
ここまでの内容をまとめましょう。実際の面接で、整理されていないテーブルを渡された場合は、次のように進めます。
- 候補キーを示し、関数従属性を列挙します。
- 原子性と繰り返しグループを確認します(1NF)。
- キーが複合キーなら、部分関数従属を確認します(2NF)。
- 非キー列から別の非キー列への従属を確認します(3NF)。
- 主キーと外部キーを付けた、変換後のテーブルを描きます。
これらの手順を声に出して説明することが、まさに面接官が評価しているポイントです。
理解度チェック
正規形についての理解度を確認しましょう。
振り返り:3NFまでの正規化
これで、正規化に関する定番の面接質問に、最初から最後まで答えられるようになりました。
- 正規化は冗長性を減らすことで、更新時異常、挿入時異常、削除時異常を取り除きます。
- 1NF:原子値、繰り返しグループなし。
- 2NF:複合キーの一部だけへの部分関数従属なし。
- 3NF:推移的な関数従属(非キー列から非キー列への従属)なし。
- 「キーに、キー全体に、そしてキーだけに」と要約できます。
- BCNFは3NFをさらに厳格にしたものです。読み取り中心の分析では、意図的に非正規化します。
よくある質問
「3NFまでの正規化」レッスンは無料ですか?
はい。「3NFまでの正規化」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Coding Interview Prepコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Coding Interview Prepコースには全4レッスンが含まれています。
「3NFまでの正規化」で何を学びますか?
第1、第2、第3正規形と、それによって解消される異常を学びます。 ブラウザで直接実行するハンズオンコードでCoding Interview Prepを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Coding Interview Prepを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのCoding Interview Prepは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「3NFまでの正規化」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このCoding Interview Prepレッスンでコードを書いて実行できますか?
はい。すべてのCoding Interview Prepレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。