データベーススペシャリスト試験対策テキスト&問題集

本書の特徴と使い方

データベーススペシャリスト試験の合格を目指す皆様へ。 本書は、データベーススペシャリスト試験の広範な出題範囲を網羅し、初心者の方から経験者の方まで、誰もが理解できるように丁寧かつ詳細に解説することを目的としています。複雑な概念も、平易な言葉と豊富な図表(Mermaid形式含む)を用いて視覚的に分かりやすく説明しています。

本書が目指すもの

本書の使い方

  1. 目次で全体像を把握: まずは本書の目次をざっと眺め、試験範囲全体の構造を把握してください。
  2. 各章のテキストを熟読: 各章のテキストを丁寧に読み込み、基本的な知識と概念を理解してください。Mermaid形式の図は、視覚的な理解を深めるのに役立ちます。
  3. 問題集で理解度をチェック: 各章のテキストを読み終えたら、対応する問題集に挑戦してください。解答だけでなく、解説もしっかりと読み込み、なぜその答えになるのか、関連する知識は何かを深掘りしてください。
  4. 午後試験対策の章を活用: 第4章と第5章は午後試験対策に特化しています。実際の試験でどのように知識を応用すべきか、解答のテクニックをここで学びましょう。
  5. 業務知識で実践力を養う: 第6章の業務知識は、午後Ⅱ問題で求められる業務理解力とデータモデリング能力の基礎となります。実際の業務をデータモデルとしてどう表現するかを学び、実践的な力を養いましょう。
  6. 繰り返し学習: 一度で全てを完璧にする必要はありません。理解が及ばない部分は、何度も読み返し、問題集を繰り返し解くことで、着実に実力をつけていきましょう。

本書が、皆様のデータベーススペシャリスト試験合格への強力な一助となることを願っています。

目次

本書の特徴と使い方

第0章 受験のススメ

第1章 SQL

第2章 DBMS

第3章 設計

第4章 午後試験対策 物理設計

第5章 午後試験対策 論理設計

第6章 業務知識

索引


第0章 受験のススメ

0.1 試験の概要

0.1.1 データベーススペシャリスト試験とは

データベーススペシャリスト試験(DB)は、情報処理推進機構(IPA)が実施する情報処理技術者試験の一つであり、高度情報処理技術者試験に分類されます。この試験は、企業活動における大量のデータを効率的かつ安全に管理・活用するための、データベースに関する専門知識とスキルを問うものです。

試験の目的と対象者

この試験は、データベースに関する深い知識と実践的な能力を持つ人材を育成し、評価することを目的としています。具体的には、以下のような役割を担う方を主な対象としています。

現代のビジネスにおいて、データは「石油に代わる21世紀の資源」とも言われるほど重要性が増しています。データベーススペシャリストは、この重要なデータを適切に扱い、企業の競争力向上に貢献する、まさになくてはならない存在です。

試験のレベルと位置づけ

情報処理技術者試験の中では、最高レベルのスキルを認定する「高度試験」の一つに位置づけられています。基本情報技術者試験や応用情報技術者試験で問われる基礎的な知識に加え、より専門的で実践的な知識、そして問題解決能力が求められます。

具体的には、リレーショナルデータベース(RDB)の概念から、SQL、トランザクション処理、正規化、データモデリング、パフォーマンスチューニング、障害回復、セキュリティ、最新のデータベース技術(NoSQL、分散データベースなど)に至るまで、幅広い分野からの出題があります。

この資格を取得することで、データベースに関する深い専門知識と、それを実務に適用できる高度なスキルを持っていることを客観的に証明できます。これにより、IT業界でのキャリアアップや専門家としての信頼性向上に大きく寄与するでしょう。


0.1.2 試験の詳細

データベーススペシャリスト試験は、年に1回、通常は秋期(10月の第3日曜日)に実施されます。試験は4つの区分に分かれており、1日で全ての試験を受験します。

graph TD subgraph "試験全体" A["午前Ⅰ"] --> B["午前Ⅱ"] --> C["午後Ⅰ"] --> D["午後Ⅱ"] end style A fill:#f9f,stroke:#333,stroke-width:2px style B fill:#f9f,stroke:#333,stroke-width:2px style C fill:#ccf,stroke:#333,stroke-width:2px style D fill:#ccf,stroke:#333,stroke-width:2px

各試験区分の概要

試験区分 試験時間 出題形式 出題数 解答数 基準点
午前Ⅰ 50分 多肢選択式(4択) 30問 30問 60点/100点
午前Ⅱ 40分 多肢選択式(4択) 25問 25問 60点/100点
午後Ⅰ 90分 記述式 3問 2問 60点/100点
午後Ⅱ 120分 記述式 2問 1問 60点/100点

合格基準(ノックダウン方式)

この試験の最大の特徴は「ノックダウン方式」が採用されている点です。これは、いずれかの試験区分で基準点(60点)に満たない場合、その時点で不合格となる厳しい採点方式です。

例えば、午前Ⅰで58点を取ってしまった場合、その後の午前Ⅱ、午後Ⅰ、午後Ⅱがたとえ満点であっても採点されることなく不合格となります。全ての試験区分で、安定して6割以上の得点を取る実力が求められます。

graph LR Start("受験開始") --> AM1{"午前Ⅰ"}; AM1 -- "基準点以上" --> AM2{"午前Ⅱ"}; AM1 -- "基準点未満" --> Fail("不合格"); AM2 -- "基準点以上" --> PM1{"午後Ⅰ"}; AM2 -- "基準点未満" --> Fail; PM1 -- "基準点以上" --> PM2{"午後Ⅱ"}; PM1 -- "基準点未満" --> Fail; PM2 -- "基準点以上" --> Pass("最終合格"); PM2 -- "基準点未満" --> Fail; style Fail fill:#fdd,stroke:#f00 style Pass fill:#ddf,stroke:#00f

午前Ⅰ試験の免除制度

以下のいずれかの条件を満たすことで、その後2年間、午前Ⅰ試験が免除されます。

  1. 応用情報技術者試験(AP)に合格する。
  2. いずれかの高度情報処理技術者試験(DBを含む)に合格する。
  3. いずれかの高度情報処理技術者試験の午前Ⅰ試験で基準点以上(60点以上)の成績を修める。

多くの受験者はこの免除制度を活用し、専門分野である午前Ⅱと午後試験の対策に集中します。


0.2 学習の計画

データベーススペシャリスト試験の合格を勝ち取るためには、戦略的な学習計画が不可欠です。特に、各試験区分で基準点を超える必要がある「ノックダウン方式」を意識し、バランスの取れた学習を心がける必要があります。

学習期間は、個人の経験や知識レベルによって異なりますが、一般的には3ヶ月〜6ヶ月が目安とされています。

本セクションでは、各試験区分に応じた具体的な学習計画を提案します。

0.2.1 午前Ⅰ試験の学習計画

対象者: 午前Ⅰ試験の免除資格がない、または免除期間が切れてしまった方。

学習の要点: 「広く浅く」、そして**「過去問至上主義」**で乗り切ること。

午前Ⅰ試験は、全ての高度試験で共通して出題されるIT全般の知識を問う試験です。テクノロジ系、マネジメント系、ストラテジ系と範囲が非常に広く、全ての分野を完璧に理解しようとすると時間がいくらあっても足りません。

幸いなことに、午前Ⅰ試験は過去に出題された問題が形を変えて繰り返し出題される傾向が非常に強いです。そのため、最も効率的な対策は過去問演習に尽きます。

具体的な学習ステップ:

  1. 直近5年分の過去問を入手する: IPAの公式サイトや、Web上の学習サイト(通称「過去問道場」など)を活用しましょう。
  2. 時間を計らずに1回分解いてみる: まずは自分の現在地を把握します。何割くらい解けるか、どの分野が苦手かを確認します。
  3. 間違えた問題と、正解したが自信がなかった問題を徹底的に復習する:
  4. 2〜3を繰り返す: 複数の年度の過去問を解くうちに、頻出の問題や分野が見えてきます。
  5. 試験直前は、何度も間違える問題だけをまとめたノートを見返す: 最終的には、コンスタントに7割〜8割の正答率を達成できる状態を目指します。

午前Ⅰ試験は、あくまで午前Ⅱ以降の専門試験に進むための「通行手形」です。完璧を目指さず、効率的に60点の壁を突破することだけを考えて学習を進めましょう。


0.2.2 午前Ⅱ試験の学習計画

学習の要点: 「狭く深く」、そして**「理屈を自分の言葉で説明できるレベル」**を目指すこと。

午前Ⅱ試験は、データベーススペシャリストとしての専門知識が問われる、この試験の核となる部分です。出題範囲はデータベース技術に特化しており、ここでの知識が午後試験の土台となります。午前Ⅰとは対照的に、単なる暗記ではなく、各技術や概念の本質的な理解が求められます。

重点学習分野:

具体的な学習ステップ:

  1. 体系的な知識のインプット:

  2. 過去問演習と徹底的な復習:

  3. 苦手分野の特定と克服:

午前Ⅱで高得点(目標は8割以上)を安定して取れるようになれば、午後試験を解くための強固な基礎知識が身についた証拠です。焦らずじっくりと、一つ一つの概念を自分のものにしていきましょう。


0.2.3 午後試験の学習計画

学習の要点: 「国語力と論理的思考力」 を駆使し、**「問題文に隠されたヒントを読み解く」**訓練を積むこと。

午後試験は、データベーススペシャリスト試験の天王山です。膨大な問題文の中から、要件、制約、課題を正確に読み取り、午前Ⅱで培った知識を応用して、記述式で解答する総合力が問われます。知識があるだけでは合格できません。

午後試験の出題傾向:

具体的な学習ステップ(5段階演習法):

  1. 【第1段階】時間を計って解く(シミュレーション)

  2. 【第2段階】時間無制限で解き直す(熟考)

  3. 【第3段階】解答例との比較・分析(ギャップ分析)

  4. 【第4段階】知識の再インプット(知識補強)

  5. 【第5段階】要約と再説明(定着)

この5段階のプロセスを最低でも5年分の過去問に対して行えば、合格は目前です。時間はかかりますが、最も着実に実力がつく方法です。


0.3 解答のテクニック

知識を蓄え、過去問演習を積んでも、試験本番で実力を100%発揮できなければ意味がありません。ここでは、限られた時間の中で1点でも多く得点するための、実践的な解答テクニックを紹介します。

0.3.1 午前試験の解答テクニック

午前Ⅰ・午前Ⅱは、1問あたり約1分半で解答する必要があるスピード勝負です。迷いを断ち切り、効率的に解答を進めるテクニックを身につけましょう。

  1. 時間配分を厳守する

  2. 消去法を徹底活用する

  3. 問題文のキーワードに注目する

  4. 常識で判断する

  5. 迷ったら最初の直感を信じる


0.3.2 午後試験の解答テクニック

午後試験の鉄則はただ一つ、**「答えは全て問題文の中にある」**です。自分の経験や知識だけで暴走せず、問題文という地図を正確に読み解くテクニックを身につけましょう。

  1. 最初の10分で問題を選び、戦略を立てる

  2. 問題文は「多色ボールペンで書き込みながら」読む

  3. 設問を先に読み、解答の「型」を意識する

  4. 解答は「聞かれたことに」「過不足なく」答える

  5. 部分点を確実に取りにいく


0.4 日々の勉強のアドバイス

長期間にわたる試験勉強は、知識だけでなく、モチベーションの維持や学習の習慣化が同じくらい重要になります。最後に、合格まで走り抜くための心構えをいくつか紹介します。

  1. 学習を「習慣」にする

  2. 仕事や実務と結びつけて考える

  3. モチベーションを管理する

  4. 体調管理も重要な試験対策


さあ、準備は整いました。次の章から、データベーススペシャリストになるための本格的な知識を学んでいきましょう!


第1章 SQL

1.1 テーブル作成

データベースにおけるテーブル作成は、データを格納するための「箱」の設計図を作る作業に例えられます。どのような種類のデータを、どのように整理して格納するかを定義する、データベース設計の基礎となる重要なステップです。

SQL(Structured Query Language)におけるテーブル作成は、DDL(Data Definition Language: データ定義言語)の一つであるCREATE TABLE文を用いて行います。

テーブルを作成する際には、以下の要素を定義します。

1.1.1 データ型

データ型は、テーブルのカラムに格納できるデータの種類を定義するものです。適切なデータ型を選択することは、データの整合性を保ち、記憶領域を効率的に使用し、クエリのパフォーマンスを向上させる上で非常に重要です。

以下に代表的なデータ型とその特徴を説明します。データベースシステム(DBMS)によって、利用できるデータ型やその名称、詳細な挙動には違いがありますが、基本的な考え方は共通しています。

1. 文字列型 (Character String Types)

2. 数値型 (Numeric Types)

3. 日付/時間型 (Date/Time Types)

4. 真偽値型 (Boolean Types)

テーブル作成例

以下は、様々なデータ型を用いた簡単なテーブル作成の例です。

CREATE TABLE Products ( product_id INT PRIMARY KEY, -- 製品ID (整数、主キー) product_name VARCHAR(100) NOT NULL, -- 製品名 (可変長文字列、NULL不許可) price DECIMAL(10, 2), -- 価格 (固定小数点数) stock_quantity INT DEFAULT 0, -- 在庫数 (整数、デフォルト値0) release_date DATE, -- 発売日 (日付) is_available BOOLEAN -- 販売中かどうか (真偽値) );

1.1.2 NULL

データベースにおけるNULLは、**「値が存在しない」「不明である」「適用できない」**といった状態を表す特殊な値です。数値の0や空文字''、または真偽値のFALSEとは明確に異なります。NULLは「未定義」の状態を示すものであり、データが存在しないことそのものを意味します。

NULLの特性

NULLが絡む演算や比較は、一般的な値とは異なる振る舞いをします。この特性を理解していないと、意図しないクエリ結果を招く可能性があるため、注意が必要です。

  1. 算術演算: NULLを含む算術演算(+, -, *, /など)の結果は、常にNULLとなります。

    -- 例: 5 + NULL は NULL となる SELECT 5 + NULL;

    これは、「不明な値に何かを加えても、結果はやはり不明である」という考え方に基づきます。

  2. 比較演算: NULLと他の値を=!=(または<>)、<>などの比較演算子で比較した場合、結果は真(TRUE)でも偽(FALSE)でもなく、UNKNOWN(不明)となります。

    -- 例: 1 = NULL や 'A' = NULL は UNKNOWN となる SELECT product_name FROM Products WHERE price = NULL; -- 意図した結果にならない

    WHERE句でUNKNOWNと評価された行は、結果セットに含まれません。このため、WHERE price = NULLという条件では、priceNULLの行は取得できません。

NULL値の検索方法 (IS NULL, IS NOT NULL)

NULLを正しく検索するためには、専用の演算子IS NULLまたはIS NOT NULLを使用します。

-- priceがNULLの製品を検索 SELECT product_name, price FROM Products WHERE price IS NULL; -- priceがNULLではない製品を検索 SELECT product_name, price FROM Products WHERE price IS NOT NULL;

NOT NULL制約

テーブルのカラム定義において、そのカラムにNULL値の格納を許可しないように設定できるのが**NOT NULL制約**です。これはデータの整合性を保つ上で非常に重要な制約となります。

NOT NULL制約が設定されたカラムには、必ず何らかの値を挿入する必要があります。NULLを挿入しようとするとエラーが発生します。

-- 製品テーブルの定義例(再掲、product_nameにNOT NULL制約) CREATE TABLE Products ( product_id INT PRIMARY KEY, product_name VARCHAR(100) NOT NULL, -- ここにNOT NULL制約 price DECIMAL(10, 2), stock_quantity INT DEFAULT 0, release_date DATE, is_available BOOLEAN ); -- product_nameに値を指定しないINSERTはエラーになる -- INSERT INTO Products (product_id, product_name) VALUES (1, NULL); -- これはエラー! INSERT INTO Products (product_id, product_name) VALUES (1, '新しい製品A'); -- OK

デフォルト値とNULL

NOT NULL制約とDEFAULT句を組み合わせることで、カラムに値が明示的に指定されなかった場合に、自動的にデフォルト値が挿入されるようにできます。これにより、常に値が存在することを保証しつつ、挿入時の手間を省くことが可能です。

-- stock_quantityにDEFAULT 0とNOT NULL制約を追加する例 CREATE TABLE Products ( product_id INT PRIMARY KEY, product_name VARCHAR(100) NOT NULL, price DECIMAL(10, 2), stock_quantity INT NOT NULL DEFAULT 0, -- NOT NULL と DEFAULT の組み合わせ release_date DATE, is_available BOOLEAN ); -- stock_quantityを省略してINSERTしても、自動的に0が挿入される INSERT INTO Products (product_id, product_name, price, release_date, is_available) VALUES (2, '新しい製品B', 19.99, '2026-03-01', TRUE); -- この場合、stock_quantityは0となる

1.2 問合せ

データベースに格納されたデータは、必要に応じて取り出し、加工して利用されます。この「データの取り出しと加工」を行うのが**問合せ(クエリ)**です。SQLでは、主にDML(Data Manipulation Language: データ操作言語)のSELECT文を使ってデータ問合せを行います。

SELECT文は、データベースから特定の条件に合致するデータを抽出し、指定した形式で結果を返すための最も基本的な、しかし最も強力なコマンドです。

ここでは、SELECT文の基本的な使い方から、データの絞り込み、並べ替え、集計といった応用的な問合せ方法について学習していきます。

1.2.1 SELECT

SELECT文は、テーブルからデータを検索し、その結果を取得するために使用します。基本的な構文は以下の通りです。

SELECT カラム名1, カラム名2, ... FROM テーブル名;

より具体的な例を見るために、以下のProductsテーブルにデータを挿入しておきます。

-- Productsテーブルの定義 (再掲) -- CREATE TABLE Products ( -- product_id INT PRIMARY KEY, -- product_name VARCHAR(100) NOT NULL, -- price DECIMAL(10, 2), -- stock_quantity INT NOT NULL DEFAULT 0, -- release_date DATE, -- is_available BOOLEAN -- ); -- テストデータ挿入 INSERT INTO Products (product_id, product_name, price, stock_quantity, release_date, is_available) VALUES (1, 'ラップトップPC', 1200.00, 50, '2025-01-15', TRUE), (2, 'ワイヤレスマウス', 25.50, 200, '2025-02-01', TRUE), (3, 'メカニカルキーボード', 75.00, 100, '2025-01-20', TRUE), (4, 'USBハブ', 12.00, 300, '2025-03-10', TRUE), (5, '外付けSSD 1TB', 90.00, 70, '2025-02-28', TRUE), (6, 'Webカメラ', 49.99, 80, '2025-01-05', FALSE), (7, 'ゲーミングヘッドセット', 60.00, 40, '2025-03-15', TRUE), (8, 'モニター 27インチ', 250.00, 30, '2025-02-10', FALSE), (9, 'タブレットスタンド', 15.00, 150, '2025-03-20', TRUE), (10, 'ポータブル充電器', 35.00, 120, '2025-01-25', TRUE);

全てのカラムと行を取得する (SELECT *)

テーブル内の全てのカラム、全ての行を取得するには、SELECTの後にアスタリスク(*)を指定します。

SELECT * FROM Products;

実務では、必要なカラムだけを指定するのが良いとされています。SELECT *は手軽ですが、不要なデータを取得することでネットワーク負荷やDBの処理負荷が増える可能性があるため、注意が必要です。

特定のカラムだけを取得する

必要なカラム名をカンマ(,)で区切って指定します。

SELECT product_name, price FROM Products;

重複行を除外する (DISTINCT)

特定カラムの値の重複を除いて、一意な値だけを取得したい場合はDISTINCTキーワードを使用します。

SELECT DISTINCT price FROM Products;

DISTINCTは、指定したカラムの組み合わせに対して適用されます。

カラムに別名をつける (AS句)

取得したカラム名が長く読みにくい場合や、複数のテーブルを結合する際にカラム名が重複する場合などに、一時的に別名(エイリアス)をつけることができます。ASキーワードは省略可能です。

SELECT product_name AS "商品名", price AS 価格 FROM Products;

演算結果をカラムとして表示する(計算フィールド)

SELECT句には、カラム名だけでなく、定数や演算式を指定することもできます。

-- 価格に消費税10%を加算した「税込価格」を表示 SELECT product_name, price, price * 1.10 AS "税込価格" FROM Products;

1.2.2 WHERE

WHERE句は、取得するデータの行を絞り込むための条件を指定します。SELECT文で最も重要な句の一つです。

SELECT カラム名 FROM テーブル名 WHERE 条件式;

比較演算子

演算子 意味
= 等しい
<> or != 等しくない
> より大きい
< より小さい
>= 以上
<= 以下
-- 価格が100ドル以上の製品を検索 SELECT product_name, price FROM Products WHERE price >= 100.00;

論理演算子

複数の条件を組み合わせるためにANDORNOTを使用します。

ANDORよりも優先順位が高いため、意図しない結果を避けるために括弧()を使うことが推奨されます。

-- 価格が50ドル以上かつ在庫が100個未満の製品 SELECT product_name, price, stock_quantity FROM Products WHERE price >= 50.00 AND stock_quantity < 100; -- 価格が20ドル未満、または在庫が200個以上の製品 SELECT product_name, price, stock_quantity FROM Products WHERE price < 20.00 OR stock_quantity >= 200;

その他の便利な演算子

-- 価格が50ドルから100ドルの範囲にある製品 SELECT product_name, price FROM Products WHERE price BETWEEN 50.00 AND 100.00; -- 製品IDが1, 3, 5の製品 SELECT product_id, product_name FROM Products WHERE product_id IN (1, 3, 5); -- 製品名に「PC」が含まれる製品 SELECT product_name FROM Products WHERE product_name LIKE '%PC%';

1.2.3 ORDER BY

ORDER BY句は、取得した結果を特定のカラムの値に基づいて並べ替えるために使用します。

-- 価格が高い順に製品を並べ替え SELECT product_name, price FROM Products ORDER BY price DESC; -- 発売日の新しい順、同じ発売日の場合は価格の安い順に並べ替え SELECT product_name, release_date, price FROM Products ORDER BY release_date DESC, price ASC;

1.3 副問合せ

**副問合せ(サブクエリ)**とは、SQL文の中に入れ子で記述されるSELECT文のことです。WHERE句やFROM句、SELECT句など、様々な場所で使用でき、より複雑な問合せを実現します。

1.3.1 一般的な副問合せ

副問合せが返す行数や列数によって、いくつかの種類に分けられます。

1.3.2 相関副問合せ

相関副問合せは、内側の副問合せが外側の主問合せのカラムを参照するタイプの副問合せです。主問合せの行が1行処理されるたびに、その行の値を参照して副問合せが実行されます。

普通の副問合せ: 内側の問合せが単独で実行可能。 相関副問合せ: 内側の問合せが外側の値に依存するため、単独では実行不可。

-- 各製品カテゴリ内で、そのカテゴリの平均価格よりも高い製品を検索 -- (Productsテーブルにcategory_idカラムが存在すると仮定) SELECT product_name, price, category_id FROM Products AS p1 WHERE price > ( SELECT AVG(p2.price) FROM Products AS p2 WHERE p2.category_id = p1.category_id -- 外側のp1を参照 );

この例では、外側のp1テーブルのcategory_idを、内側のp2テーブルの絞り込み条件に使っています。これにより、「自分と同じカテゴリの平均価格」を計算し、比較することが可能になります。


1.4 グループ化

1.4.1 集約関数

集約関数は、複数の行をまとめて一つの結果を返す関数です。GROUP BY句と組み合わせて使うことが多いですが、単独でも使用できます。

関数 説明
COUNT() 行数を数える。COUNT(*)は全行、COUNT(カラム名)はNULL以外の行を数える。
SUM() 数値の合計を計算する。
AVG() 数値の平均を計算する。
MAX() 最大値を求める。
MIN() 最小値を求める。
-- 製品の総数、価格の合計、平均価格を計算 SELECT COUNT(*), SUM(price), AVG(price) FROM Products;

1.4.2 グループ化した後に絞り込みを行う (GROUP BY, HAVING)

GROUP BY句は、特定カラムの値が同じ行をグループにまとめ、各グループに対して集約関数を適用します。

HAVING句は、GROUP BYで作成されたグループに対して条件を指定し、結果を絞り込むために使います。WHERE句が行を絞り込むのに対し、HAVING句はグループを絞り込むという違いがあります。

-- 各カテゴリIDごとの製品数と平均価格を計算 -- (Productsテーブルにcategory_idカラムが存在すると仮定) SELECT category_id, COUNT(product_id), AVG(price) FROM Products GROUP BY category_id; -- 上記の結果から、製品数が3つ以上あるカテゴリのみを抽出 SELECT category_id, COUNT(product_id) AS product_count, AVG(price) FROM Products GROUP BY category_id HAVING COUNT(product_id) >= 3; -- HAVINGでグループを絞り込み

重要: WHERE句はグループ化の前に評価され、HAVING句はグループ化の後に評価されます。


1.5 関係代数

関係代数は、リレーショナルデータベースの操作を数学的に体系化したもので、SQLの理論的な基盤となっています。集合論に基づいており、 直積 などの演算があります。

1.5.1 和 (UNION)

2つのSELECT文の結果を結合し、重複行を除外して表示します。重複行を含めたい場合はUNION ALLを使用します。

SELECT product_id, product_name FROM Products WHERE price > 100 UNION SELECT product_id, product_name FROM Products WHERE stock_quantity < 50;

1.5.2 差 (EXCEPT / MINUS)

最初のSELECT文の結果から、2番目のSELECT文の結果に含まれる行を除外します。

SELECT product_id, product_name FROM Products WHERE price > 50 EXCEPT SELECT product_id, product_name FROM Products WHERE stock_quantity < 100;

1.5.3 積 (INTERSECT)

両方のSELECT文の結果に共通して存在する行のみを返します。

SELECT product_id, product_name FROM Products WHERE price > 50 INTERSECT SELECT product_id, product_name FROM Products WHERE stock_quantity < 100;

1.5.4 直積 (CROSS JOIN)

2つのテーブルの全ての行の組み合わせを返します。CROSS JOINキーワードまたはFROM句でテーブルをカンマ区切りにすることで実現できます。

SELECT p.product_name, c.category_name FROM Products p CROSS JOIN Categories c;

1.5.5 商

「テーブルAの特定の属性値に紐づく全ての値が、テーブルBに存在する」ような行をテーブルAから見つけ出す演算です。SQLには直接の演算子はありませんが、NOT EXISTSなどを駆使して実現します。これは非常に高度な概念であり、試験でも難問として出題されることがあります。


1.6 結合

複数のテーブルを、関連するカラムをキーにして連結し、一つの結果として取得する操作です。結合を理解するために、Categoriesテーブルを新しく定義し、Productsテーブルを更新します。

-- Categoriesテーブル作成 CREATE TABLE Categories ( category_id INT PRIMARY KEY, category_name VARCHAR(50) NOT NULL ); INSERT INTO Categories VALUES (1, 'PC本体'), (2, 'PC周辺機器'), (3, 'その他'); -- Productsテーブルにcategory_idカラムを追加 ALTER TABLE Products ADD COLUMN category_id INT; UPDATE Products SET category_id = 1 WHERE product_id IN (1, 8); UPDATE Products SET category_id = 2 WHERE product_id IN (2, 3, 4, 5, 6, 7, 9); UPDATE Products SET category_id = 3 WHERE product_id = 10;
graph TD Categories -- "1対多" --> Products;

1.6.1, 1.6.2 内部結合 (INNER JOIN)

両方のテーブルに存在する、結合キーの値が一致する行だけを返します。

SELECT p.product_name, c.category_name FROM Products AS p INNER JOIN Categories AS c ON p.category_id = c.category_id;

1.6.3 外部結合 (LEFT/RIGHT OUTER JOIN)

LEFT JOINは左側のテーブルの行を全て返し、右側のテーブルに一致する行がない場合はNULLを返します。RIGHT JOINはその逆です。OUTERは省略可能です。

-- 全ての製品とそのカテゴリ名を表示(カテゴリ未設定の製品も表示) SELECT p.product_name, c.category_name FROM Products AS p LEFT JOIN Categories AS c ON p.category_id = c.category_id;

1.6.4 全外部結合 (FULL OUTER JOIN)

両方のテーブルの全ての行を返し、一致する行がない場合は互いにNULLを返します。

SELECT p.product_name, c.category_name FROM Products AS p FULL OUTER JOIN Categories AS c ON p.category_id = c.category_id;

1.7 追加、更新、削除

1.7.1 INSERT

テーブルに新しい行を追加します。

INSERT INTO Categories (category_id, category_name) VALUES (4, 'ソフトウェア');

1.7.2 UPDATE

既存の行のデータを更新します。WHERE句を忘れると全ての行が更新されるため、絶対に忘れないでください。

UPDATE Products SET price = price * 0.9 WHERE release_date < '2025-02-01';

1.7.3 DELETE

既存の行を削除します。WHERE句を忘れると全ての行が削除されるため、絶対に忘れないでください。

DELETE FROM Products WHERE is_available = FALSE;

1.8 整合性制約

データの矛盾や不正を防ぎ、整合性を保つためのルールです。テーブル作成時や変更時に定義します。


1.9 ビュー

ビューは、一つ以上のテーブルから作られる仮想的なテーブルです。SELECT文をデータベースに保存し、名前を付けたものと考えることができます。

利点:

CREATE VIEW V_AvailableProducts AS SELECT product_name, price, category_name FROM Products p JOIN Categories c ON p.category_id = c.category_id WHERE p.is_available = TRUE; -- ビューを通常のテーブルのように使用 SELECT * FROM V_AvailableProducts WHERE price > 50;

1.9.1 更新可能ビュー

特定の条件を満たすビューは、INSERT, UPDATE, DELETEが可能です。 主な条件:


1.10 ユーザと権限

1.10.1 ユーザ

データベースにアクセスする主体。CREATE USERで作成します。

CREATE USER 'gemini_user'@'localhost' IDENTIFIED BY 'password';

1.10.2 権限

ユーザがデータベースやそのオブジェクトに対して何ができるかを定義します。GRANTで権限を付与し、REVOKEで剥奪します。

-- gemini_userにProductsテーブルのSELECT権限を付与 GRANT SELECT ON database_name.Products TO 'gemini_user'@'localhost'; -- 全ての権限を付与 GRANT ALL PRIVILEGES ON database_name.* TO 'gemini_user'@'localhost'; -- SELECT権限を剥奪 REVOKE SELECT ON database_name.Products FROM 'gemini_user'@'localhost';

1.11 ストアドプロシージャ

一連のSQL処理をまとめてデータベースに保存し、名前を付けて呼び出せるようにしたものです。

利点:

-- 特定の価格以上の製品を検索するプロシージャ DELIMITER // CREATE PROCEDURE GetProductsByPrice(IN min_price DECIMAL(10,2)) BEGIN SELECT product_name, price FROM Products WHERE price >= min_price; END // DELIMITER ; -- プロシージャの呼び出し CALL GetProductsByPrice(100.00);

第1章 SQL 問題集 (20問)


問題 1 (データ型)

ある製品の価格を「9999.99」のように、小数点以下2桁まで正確に格納する必要があります。この場合、価格を格納するカラムに最も適したデータ型は次のうちどれか。

ア. FLOAT
イ. INT
ウ. VARCHAR(10)
エ. DECIMAL(6, 2)

解答と解説

解答: エ

解説:
DECIMAL(p, s)またはNUMERIC(p, s)は、p(精度)で指定された総桁数を持ち、そのうちs(スケール)で指定された桁数が小数点以下となる、正確な数値を格納するためのデータ型です。通貨のような誤差が許されない値の格納に最適です。


問題 2 (NULL)

SQL文 SELECT 100 * NULL; を実行した結果として正しいものはどれか。

ア. 0
イ. 100
ウ. NULL
エ. エラーが発生する

解答と解説

解答: ウ

解説:
NULLは「不明」を表す特殊な値です。NULLを含む算術演算(+, -, *, /など)の結果は、常にNULLになります。「不明な値」に何を掛けても、結果は「不明」であるという考え方に基づきます。


問題 3 (WHERE句)

Productsテーブルから、priceが100以上で、かつis_availableTRUEである製品を抽出するSQL文のWHERE句として正しいものを完成させなさい。

SELECT product_name, price FROM Products WHERE [ ______ ];
解答と解説

解答: price >= 100 AND is_available = TRUE

解説:
「AかつB」という条件は、AND演算子を用いて表現します。それぞれの条件式をANDで結合することで、両方の条件を満たす行のみを絞り込むことができます。


問題 4 (ORDER BY)

Productsテーブルの製品を、stock_quantity(在庫数)の多い順に並べ、在庫数が同じ場合はproduct_name(製品名)のアルファベット昇順(A→Z)に並べ替えるORDER BY句を完成させなさい。

SELECT product_name, stock_quantity FROM Products ORDER BY [ ______ ];
解答と解説

解答: stock_quantity DESC, product_name ASC

解説:
ORDER BY句では、複数のカラムをカンマで区切って指定することで、複数のキーで並べ替えが可能です。最初のキー(stock_quantity)で並べ替え、値が同じ行グループ内で次のキー(product_name)で並べ替えます。DESCは降順(多い順)、ASCは昇順(A→Z)を指定します。ASCはデフォルトなので省略可能です。


問題 5 (集約関数)

Productsテーブルの全製品の平均価格をavg_priceという別名で取得するSQL文として正しいものはどれか。

ア. SELECT AVG(price) FROM Products AS avg_price;
イ. SELECT AVG(price) AS avg_price FROM Products;
ウ. SELECT price AS avg_price FROM Products GROUP BY price;
エ. SELECT TOTAL(price) AS avg_price FROM Products;

解答と解説

解答: イ

解説:
平均値を求めるには集約関数AVG()を使用します。カラムの別名はAS句を用いて指定します。


問題 6 (GROUP BY / HAVING)

Productsテーブルをcategory_idでグループ化し、グループ内の製品数が2つ以上あるカテゴリIDとその製品数を取得するSQL文を完成させなさい。

SELECT category_id, COUNT(product_id) FROM Products GROUP BY category_id HAVING [ ______ ];
解答と解説

解答: COUNT(product_id) >= 2

解説:
GROUP BY句で作成したグループに対して条件を指定するにはHAVING句を使用します。WHERE句はグループ化の前に個々の行をフィルタリングするのに対し、HAVING句はグループ化の後に集約関数の結果などを用いてグループをフィルタリングします。


問題 7 (副問合せ)

Productsテーブルにおいて、製品ID 4 (USBハブ) の価格と同じ価格の、USBハブ以外の製品名を取得するSQL文を完成させなさい。

SELECT product_name FROM Products WHERE price = (SELECT price FROM Products WHERE product_id = 4) AND [ ______ ];
解答と解説

解答: product_id <> 4

解説:
副問合せ (SELECT price FROM Products WHERE product_id = 4) を使って、USBハブの価格(12.00)を取得します。主問合せでは、その価格と一致し、かつ製品IDが4ではない(USBハブ自身を除く)という条件を指定します。


問題 8 (JOIN)

INNER JOINLEFT JOINの主な違いは何か。簡潔に説明しなさい。

解答と解説

解答:
INNER JOINは両方のテーブルに結合キーが一致する行だけを返すのに対し、LEFT JOINは左側のテーブルの行をすべて返し、右側のテーブルに一致する行がない場合はNULLとして返す。

解説:
INNER JOINは両方のテーブルに共通のデータのみ、LEFT JOIN(外部結合)は片方のテーブルのデータを全て残す、という点が根本的な違いです。


問題 9 (関係代数)

2つのSELECT文の結果セットの共通部分(両方に存在する行)のみを返すSQLの集合演算子は何か。

ア. UNION
イ. EXCEPT (または MINUS)
ウ. INTERSECT
エ. CROSS JOIN

解答と解説

解答: ウ

解説:


問題 10 (DML)

Productsテーブルからproduct_id6の行を削除するSQL文として正しいものはどれか。

ア. DROP FROM Products WHERE product_id = 6;
イ. DELETE FROM Products WHERE product_id = 6;
ウ. UPDATE Products WHERE product_id = 6;
エ. REMOVE FROM Products WHERE product_id = 6;

解答と解説

解答: イ

解説:
テーブルから行を削除するにはDELETE文を使用します。DROPはテーブルそのものを削除するDDL文です。REMOVEは標準SQLにはありません。


問題 11 (制約)

Productsテーブルのpriceカラムに「価格は0以上でなければならない」というルールを追加したい。テーブル作成時にこのルールを定義する制約は何か。

ア. UNIQUE
イ. PRIMARY KEY
ウ. FOREIGN KEY
エ. CHECK

解答と解説

解答: エ

解説:
CHECK制約は、カラムが満たすべき条件式を定義するためのものです。CHECK (price >= 0)と記述することで、0未満の価格が挿入・更新されるのを防ぐことができます。


問題 12 (ビュー)

ビュー(VIEW)を使用する利点として、適切でないものはどれか。

ア. 複雑な問合せを単純化できる。
イ. ユーザーごとに見せるデータを制限し、セキュリティを向上できる。
ウ. 元のテーブルへのデータ更新速度を大幅に向上させる。
エ. 元のテーブル構造の変更が、ビューを利用するアプリケーションに影響を与えにくくする。

解答と解説

解答: ウ

解説:
ビューは保存されたSELECT文であり、それ自体がデータ更新を高速化するわけではありません。むしろ、複雑なビューに対する問合せは、パフォーマンスが低下することさえあります。ア、イ、エはビューの代表的な利点です。


問題 13 (権限)

sales_userというユーザーに、Productsテーブルのデータを更新する権限のみを与えたい。正しいSQL文はどれか。

ア. GRANT UPDATE ON Products TO sales_user;
イ. PERMIT UPDATE ON Products TO sales_user;
ウ. ALLOW UPDATE ON Products TO sales_user;
エ. UPDATE Products FOR sales_user;

解答と解説

解答: ア

解説:
データベースオブジェクトに対する権限をユーザーに付与するにはGRANT文を使用します。構文は GRANT 権限 ON オブジェクト TO ユーザー; となります。


問題 14 (ストアドプロシージャ)

ストアドプロシージャに関する記述として、最も適切なものはどれか。

ア. クライアント側で実行される一連のSQL手続きである。 イ. 複数のSQL文を1回のネットワーク通信で実行できるため、ネットワーク負荷を軽減できる。 ウ. 主にテーブル構造の定義(DDL)を目的として使用される。 エ. 実行のたびにSQLがコンパイルされるため、パフォーマンスは低下する。

解答と解説

解答: イ

解説:
ストアドプロシージャはデータベースサーバ側に保存され、実行されます。事前にコンパイルされるためパフォーマンスが向上し、複数の処理を1回の呼び出し(CALL)で実行できるため、クライアントとサーバ間の通信回数が減り、ネットワーク負荷を軽減します。


問題 15 (LIKE演算子)

Productsテーブルから、product_nameが「キーボード」で終わる製品を検索するWHERE句の条件式として正しいものはどれか。

ア. product_name LIKE 'キーボード_' イ. product_name LIKE '%キーボード' ウ. product_name LIKE '_キーボード' エ. product_name LIKE 'キーボード%'

解答と解説

解答: イ

解説:
LIKE演算子で使われるワイルドカードのうち、%は「0文字以上の任意の文字列」を表します。'%キーボード'とすることで、「キーボード」という文字列で終わる全ての製品名を検索できます。


問題 16 (相関副問合せ)

相関副問合せに関する記述として、最も適切なものはどれか。

ア. 主問合せとは独立して単独で実行できる。 イ. 主問合せの行ごとに繰り返し実行されるため、一般的にパフォーマンスは良くない。 ウ. 主にFROM句でインラインビューとして使用される。 エ. 必ずIN演算子と共に使用する必要がある。

解答と解説

解答: イ

解説:
相関副問合せは、主問合せ(外側)の行の値を参照して副問合せ(内側)が実行されます。そのため、主問合せの行数分だけ副問合せが繰り返し実行されることになり、処理対象の行数が多い場合にはパフォーマンスの低下を招くことがあります。


問題 17 (DELETEとTRUNCATE)

テーブルの全行を削除する際にDELETE文とTRUNCATE TABLE文では挙動が異なる。その違いについて簡潔に説明しなさい。

解答と解説

解答:
DELETEは行を1行ずつ削除し、その操作はトランザクションログに記録されるため、ロールバックが可能。一方、TRUNCATEはテーブルを再作成するのに近い内部動作で、高速だが操作はロールバックできないことが多い。また、DELETEではWHERE句が使えるが、TRUNCATEは全行削除しかできない。


問題 18 (主キーとUNIQUE)

PRIMARY KEY制約とUNIQUE制約の共通点と相違点を簡潔に説明しなさい。

解答と解説

解答:


問題 19 (SQL実行順序)

SELECT文において、WHERE句とHAVING句は、論理的にどちらが先に評価されるか。

解答と解説

解答: WHERE

解説:
SQLの論理的な実行順序では、FROM句で対象テーブルが決定された後、WHERE句で個々の行がフィルタリングされます。その後、GROUP BY句でグループ化が行われ、最後にHAVING句でそのグループがフィルタリングされます。


問題 20 (外部結合)

Productsテーブルには存在するが、Categoriesテーブルにはまだ登録されていないcategory_idを持つ製品(例えば、category_idNULLの製品)を見つけ出すSQL文を完成させなさい。

SELECT p.product_name, p.category_id FROM Products p LEFT JOIN Categories c ON p.category_id = c.category_id WHERE [ ______ ];
解答と解説

解答: c.category_id IS NULL

解説:
LEFT JOINは左側(Products)のテーブルの行を全て返します。右側(Categories)にcategory_idが一致する行がない場合、右側のテーブルのカラム(c.category_idなど)はNULLになります。したがって、WHERE c.category_id IS NULLという条件を指定することで、カテゴリが存在しない製品を特定できます。

第2章 DBMS

2.1 索引

データベースにおける**索引(インデックス)**は、書籍の「索引」や電話帳の「見出し」のようなものです。目的のデータを探し出す時間を劇的に短縮するために使用されます。

なぜ索引が必要か?

テーブルに索引が設定されていない場合、データベースはデータを検索する際に、テーブルの全行を最初から最後まで順に読み込む必要があります(これをフルテーブルスキャンと呼びます)。データ量が少なければ問題ありませんが、数百万、数千万といった膨大なデータの中から特定の行を探し出す場合、フルテーブルスキャンでは非常に時間がかかってしまいます。

索引は、特定のカラムの値と、その値が格納されているデータ行の物理的な位置(ROWIDやポインタなど)を関連付けて管理します。これにより、目的の値を持つ行を直接見つけ出すことができるため、検索(SELECT文)のパフォーマンスが向上します。

索引のメリット・デメリット

メリット デメリット
SELECT文によるデータ検索が高速化される INSERT, UPDATE, DELETEが遅くなる(索引の更新)
ORDER BY句によるソートが高速化される ディスク容量を消費する(索引自体のデータ)
JOIN操作のパフォーマンスが向上する DBMSのメモリを消費する
WHERE句での条件指定が高速化される

索引を作成すべきケース

索引の過剰な作成は避ける

メリットがあるからといって、無闇に多くの索引を作成するのは避けるべきです。索引の数が増えるほど、データの更新時に索引自体も更新する必要が生じるため、INSERT, UPDATE, DELETEのパフォーマンスが低下します。また、ディスク容量も消費します。

適切な索引設計は、データベースのパフォーマンスチューニングにおいて非常に重要な要素となります。

2.1.1 索引探索の仕組み

データベースで最も一般的に使用される索引の構造は**B-Tree(B+Tree)**です。B-Treeはバランスの取れた木構造をしており、どのようなキー値を探す場合でも、ほぼ同じ深さのノードをたどることで高速に目的のデータに到達できます。

B-Treeの構造

B-Treeは以下の要素で構成されます。

graph TD A["ルートノード"] --> B("ブランチノード"); A --> C("ブランチノード"); B --> D("リーフノード"); B --> E("リーフノード"); C --> F("リーフノード"); C --> G("リーフノード"); D -- "次へ" --> E; E -- "次へ" --> F; F -- "次へ" --> G; subgraph "リーフノード層" D; E; F; G; end

索引探索のプロセス

B-Treeでの索引探索は、以下のような手順で行われます。

  1. ルートノードの読み込み: 探索対象のキー値とルートノード内のキー値を比較し、次に参照すべきブランチノードを特定します。
  2. ブランチノードの辿り: 1で特定されたブランチノードを読み込み、同様にキー値を比較して、さらに下位のノードへのポインタを決定します。このプロセスを繰り返して木の深さを降っていきます。
  3. リーフノードへの到達: 最終的に、目的のキー値を含むリーフノードに到達します。
  4. データ行の取得: リーフノード内で目的のキー値を見つけたら、そこに格納されているROWID(または物理アドレス)を使用して、テーブル本体から実際のデータ行を読み込みます。

この仕組みにより、大量のデータの中からでも、わずか数回のディスクI/O(ディスクアクセス)で目的のデータにたどり着くことが可能になります。


2.1.2 索引探索の種類

索引が実際にどのように利用されるかには、いくつかのパターンがあります。

  1. 索引一意スキャン (Index Unique Scan)

  2. 索引レンジスキャン (Index Range Scan)

  3. 索引フルスキャン (Index Full Scan)

  4. スキップスキャン (Index Skip Scan)

2.1.3 索引の構造

索引の論理構造はB-Treeが一般的ですが、物理的なデータの格納方法によって、さらにいくつかの種類があります。

  1. クラスタ化インデックス (Clustered Index)

  2. 非クラスタ化インデックス (Non-Clustered Index)

  3. 複合索引 (Composite Index)

  4. カバリングインデックス (Covering Index / 包含インデックス)


2.2 トランザクション

2.2.1 トランザクションとは

トランザクションとは、データベースにおいて一連の処理を一つの論理的な単位として扱うことを指します。これは「全て実行されるか、全く実行されないか」のどちらかであり、途中で失敗した場合は全ての変更が取り消されます。

例として、銀行口座Aから口座Bへ10,000円を送金する処理を考えます。この処理は以下のステップからなります。

  1. 口座Aから10,000円を引き出す。
  2. 口座Bに10,000円を振り込む。

もし1の処理は成功したが、2の処理が失敗した場合、口座Aからはお金が減ったのに口座Bには増えないという矛盾した状態が発生します。このようなデータの不整合を防ぐためにトランザクションが利用されます。

graph LR A["トランザクション開始"] --> B{"処理1"}; B --> C{"処理2"}; C --> D{"全ての処理成功?"}; D -- "はい" --> E["COMMIT 変更確定"]; D -- "いいえ" --> F["ROLLBACK 変更破棄"]; E --> G["トランザクション終了"]; F --> G;

2.2.2 ACID特性

トランザクションには、その信頼性を保証するための4つの重要な特性があります。これらは頭文字を取ってACID特性と呼ばれます。

  1. Atomicity (原子性)

  2. Consistency (一貫性)

  3. Isolation (独立性)

  4. Durability (永続性)

2.2.3 MVCC (Multi-Version Concurrency Control)

MVCCは「Multi-Version Concurrency Control」の略で、日本語では「多版型同時実行制御」などと訳されます。複数のトランザクションが同時にデータにアクセスする際の競合を減らし、データベースの同時実行性能を高めるための技術です。

課題:読み取りと書き込みの競合

従来の排他制御(ロック)では、あるトランザクションがデータを更新している間は、他のトランザクションはそのデータを読み取ることができません(書き込み中に読み取ると不整合が発生するため)。これにより、読み取り中心のシステムでも、書き込みが頻繁に発生すると読み取り処理がブロックされ、性能が低下するという課題がありました。

MVCCの解決策

MVCCでは、データが更新される際に、元のデータを上書きするのではなく、新しいバージョンのデータを作成します。これにより、複数のバージョンのデータがデータベース内に共存することになります。

graph LR A["データX バージョン1"] --> B{"T1が読み取り開始"}; A --> C{"T2が書き込み開始"}; C --> D["データX バージョン2を生成"]; D --> E["T2 COMMIT"]; B -- "バージョン1を読み取り中" --> F["T1完了"];

MVCCのメリット

MVCCのデメリット

PostgreSQLやOracleなどの多くのリレーショナルデータベースでMVCCが採用されています。

2.2.4 排他制御 (Concurrency Control)

排他制御は、複数のトランザクションが同時にデータベースにアクセスした際に、データの整合性を保つための仕組みです。主に**ロック(Lock)**という方法が使われます。

ロックの種類

  1. 共有ロック (Shared Lock / Sロック)

  2. 専有ロック (Exclusive Lock / Xロック)

graph TD Data["データA"] --> S1{"T1: Sロック要求 _読み取り"}; S1 -- "Sロック取得" --> S2{"T2: Sロック要求 _読み取り"}; S2 -- "Sロック取得" --> X1{"T3: Xロック要求 _書き込み"}; X1 -- "ブロックされる" --> Wait["待機"]; S2 -- "Sロック解除" --> S1解除{"T1, T2: Sロック解除"}; S1解除 --> X1取得{"T3: Xロック取得"};

ロックの粒度

ロックは、対象となるデータの範囲(粒度)によって、以下のようになります。

一般的に、粒度が細かいほど同時実行性は高まりますが、ロック管理のオーバーヘッドが増加します。DBMSは、問合せの内容やデータ量に応じて、適切な粒度のロックを自動的に選択します。

2.2.5 直列化可能 (Serializable)

直列化可能性(Serializable)とは、複数のトランザクションが並行して実行された場合でも、その結果が、あたかもそれらのトランザクションが何らかの順序で一つずつ(直列に)実行された場合と同じになるという保証のことです。これはトランザクションの独立性(Isolation)の最高レベルであり、最も厳格な整合性を保証します。

直列実行と並行実行

直列化可能性の重要性

並行実行時に直列化可能性が保証されていれば、プログラマはあたかもトランザクションが直列に実行されるかのようにアプリケーションを設計・実装できるため、並行処理による複雑な問題を考慮する必要がなくなります。これにより、アプリケーション開発の難易度が下がり、バグの発生を抑えることができます。

実現方法

直列化可能性は、主に以下の技術によって実現されます。

2.2.6 デッドロック (Deadlock)

デッドロックとは、複数のトランザクションが互いに相手がロックしている資源の解放を待ち合い、結果としてどのトランザクションも処理を先に進められなくなる状態のことです。

デッドロックの発生例

トランザクションT1とT2が、データAとデータBのロックを要求する例で考えます。

graph TD T1["トランザクションT1"] -- "データAをロック" --> A("データA"); T2["トランザクションT2"] -- "データBをロック" --> B("データB"); A -- "データBを待機" --> T1; B -- "データAを待機" --> T2;
  1. T1がデータAに排他ロックをかける。
  2. T2がデータBに排他ロックをかける。
  3. T1がデータBに排他ロックをかけようとするが、T2がロックしているため待機状態になる。
  4. T2がデータAに排他ロックをかけようとするが、T1がロックしているため待機状態になる。

結果として、T1はT2がBを解放するのを待ち、T2はT1がAを解放するのを待つという無限ループに陥り、どちらのトランザクションも進行できなくなります。

デッドロックの検出と解消

ほとんどのDBMSはデッドロックを自動的に検出する機能を持っています。デッドロックを検出すると、DBMSは一方のトランザクション(これを**犠牲者(Victim)**と呼びます)を強制的に中断させ、ROLLBACKします。これにより、犠牲者トランザクションがロックしていた資源が解放され、もう一方のトランザクションは処理を続行できるようになります。犠牲者となったトランザクションは、後で再実行されることになります。

デッドロックの回避策

デッドロックの発生を完全に防ぐことは難しいですが、以下の対策を講じることで発生頻度を減らすことができます。

  1. ロックの順序を統一する: 複数のデータにロックをかける必要がある場合、全てのトランザクションで同じ順序でロックをかけるようにする。
  2. ロックの粒度を適切にする: 必要以上に大きな範囲にロックをかけない。
  3. トランザクションを短くする: ロックを保持する時間を短くすることで、競合の機会を減らす。
  4. 悲観的ロックと楽観的ロックを使い分ける: 競合が少ない場合は楽観的ロック(更新時チェック)を利用するなど。

2.2.7 独立性レベル (Isolation Levels)

トランザクションの独立性(Isolation)は、複数のトランザクションが同時に実行される際に、互いの処理がどの程度影響し合うかを定義するものです。SQL標準では、以下の4つの分離レベル(Isolation Level)が定義されており、それぞれ発生しうる現象(Anomaly)を防ぐ度合いが異なります。

graph TD SERIALIZABLE --> REPEATABLE_READ; REPEATABLE_READ --> READ_COMMITTED; READ_COMMITTED --> READ_UNCOMMITTED; subgraph "独立性レベル Isolation Levels" SERIALIZABLE; REPEATABLE_READ; READ_COMMITTED; READ_UNCOMMITTED; end subgraph "発生しうる現象 Anomalies" DIRTY_READ["ダーティリード"]; NON_REPEATABLE_READ["ノンリピータブルリード"]; PHANTOM_READ["ファントムリード"]; end READ_UNCOMMITTED -- "許容" --> DIRTY_READ; READ_COMMITTED -- "許容" --> NON_REPEATABLE_READ; READ_COMMITTED -- "許容" --> PHANTOM_READ; REPEATABLE_READ -- "許容" --> PHANTOM_READ;

発生しうる現象

  1. ダーティリード (Dirty Read):

  2. ノンリピータブルリード (Non-Repeatable Read):

  3. ファントムリード (Phantom Read):

SQL標準の分離レベル

  1. READ UNCOMMITTED (未コミット読み取り)

  2. READ COMMITTED (コミット済み読み取り)

  3. REPEATABLE READ (反復可能読み取り)

  4. SERIALIZABLE (直列化可能)

適切な分離レベルの選択は、アプリケーションの要件(整合性の厳密さ、パフォーマンス、同時実行性など)に基づいて慎重に行う必要があります。


2.3 障害管理

データベースシステムは、様々な障害(ハードウェア故障、ソフトウェアエラー、電力供給停止など)が発生しても、データを保護し、可能な限り早く正常な状態に復旧できる仕組みを持っています。これが**障害管理(リカバリ)**です。

2.3.1 チェックポイント (Checkpoint)

データベースは、ディスク上のデータファイルとメモリ上のバッファキャッシュ(変更されたデータが一時的に保持される領域)を持っています。更新処理はまずバッファキャッシュ上で行われ、その後非同期的にディスクに書き込まれます。

チェックポイントとは、データベースのバッファキャッシュ内の変更されたデータを強制的にディスク上のデータファイルに書き出す処理のことです。

チェックポイントの目的

DBMSは、一定時間ごとや、特定のイベント(例えば、ログファイルのサイズが閾値を超えた時)が発生した際に、自動的にチェックポイント処理を実行します。

2.3.2 障害回復 (Recovery)

データベースシステムは、以下の要素を組み合わせて障害から回復します。

  1. ログファイル(ジャーナル):

  2. データファイル:

  3. バックアップ:

障害回復のプロセス(ロールフォワードとロールバック)

データベース障害発生時、DBMSはログファイルを利用して、データベースを整合性の取れた状態に復旧します。

これらの仕組みによって、データベースは高い信頼性と可用性を提供しています。


2.4 最新データベース技術

2.4.1 NoSQL

近年、Webサービスやビッグデータの登場により、従来のリレーショナルデータベース(RDBMS)だけでは対応しきれない課題(大量のデータ、高いスケーラビリティ、柔軟なスキーマなど)が浮上しました。これに対応するために登場したのが、**NoSQL(Not only SQL)**と呼ばれる、RDBMS以外の様々なデータストア技術です。

NoSQL登場の背景

NoSQLの主な特徴

NoSQLの分類

NoSQLは、そのデータモデルによっていくつかの主要なカテゴリに分類されます。

graph TD NoSQL["NoSQL"] --> KV["Key-Value Store"]; NoSQL --> Doc["Document Store"]; NoSQL --> CF["Column-Family Store"]; NoSQL --> Graph["Graph Database"]; KV -- "例" --> Redis; KV -- "例" --> DynamoDB; Doc -- "例" --> MongoDB; Doc -- "例" --> Couchbase; CF -- "例" --> Cassandra; CF -- "例" --> HBase; Graph -- "例" --> Neo4j;
  1. Key-Value Store (KVS)

  2. Document Store

  3. Column-Family Store

  4. Graph Database

2.4.2 分散データベース (Distributed Database)

分散データベースとは、一つの論理的なデータベースが、物理的にはネットワークで接続された複数のコンピュータ(ノード)に分散して格納・管理されているシステムのことです。ユーザーからは単一のデータベースのように見えますが、内部ではデータが複数の場所に分割して保持されています。

分散データベースの目的

分散データベースの課題

CAP定理

分散システムにおける重要な概念にCAP定理があります。これは、以下の3つの特性のうち、同時に2つしか完全に満たすことはできない、というものです。

多くの分散データベースやNoSQLシステムは、このCAP定理のトレードオフを考慮し、特定の特性を優先するように設計されています。例えば、可用性と分断耐性を優先し、一貫性を「最終的な一貫性」とするシステムが多く存在します。


第2章 DBMS 問題集 (20問)


問題 1 (索引の役割)

データベースにおいて索引(インデックス)を使用する主な目的として、最も適切なものはどれか。

ア. データの重複を自動的に排除するため。
イ. INSERTUPDATEDELETEの処理速度を向上させるため。
ウ. SELECT文によるデータ検索の処理速度を向上させるため。
エ. データベースの物理的な容量を削減するため。

解答と解説

解答: ウ

解説:
索引は、特定のカラムの値をキーとしてデータ行へのポインタを管理することで、SELECT文による検索やソート処理を高速化します。データの重複排除は主にPRIMARY KEYUNIQUE制約の役割であり、INSERT等のDML操作は索引のメンテナンスコストがかかるため遅くなります。索引自体もデータであるため、物理容量は増加します。


問題 2 (B-Tree索引)

B-Tree(B+Tree)索引の構造において、実際のデータ行へのポインタ(ROWIDなど)を格納しているのは主にどのノードか。

ア. ルートノード
イ. ブランチノード
ウ. リーフノード
エ. メタデータノード

解答と解説

解答: ウ

解説:
B-Tree索引では、ルートノードとブランチノードは探索のためのキー値と下位ノードへのポインタを保持し、リーフノードが実際のキー値とデータ行へのポインタを格納しています。リーフノードは通常、範囲検索を効率化するために相互に連結されています。


問題 3 (索引のデメリット)

索引のデメリットとして、適切でないものはどれか。

ア. 索引の作成や再構築に時間がかかる。
イ. SELECT文によるデータ検索が遅くなる。
ウ. INSERTUPDATEDELETEなどのデータ変更時に索引の更新が必要となる。
エ. ディスクストレージを消費する。

解答と解説

解答: イ

解説:
索引はSELECT文によるデータ検索を高速化するためのものです。データ検索が遅くなるのは索引のデメリットではありません。索引の作成、更新コスト、ストレージ消費はデメリットです。


問題 4 (クラスタ化インデックス)

クラスタ化インデックス(Clustered Index)に関する説明として、最も適切なものはどれか。

ア. 1つのテーブルに複数作成できる。
イ. 索引のキー順にテーブルのデータ行が物理的に並べ替えられて格納される。
ウ. 常に非クラスタ化インデックスよりも検索性能が優れている。
エ. VARCHAR型のカラムにのみ作成できる。

解答と解説

解答: イ

解説:
クラスタ化インデックスは、索引のキー順にデータ行が物理的に格納されるため、1つのテーブルに1つしか作成できません(アは誤り)。物理的な並び順と索引が一致するため、多くの場合高速ですが、常に非クラスタ化インデックスより優れているとは限りません(ウは誤り)。データ型の制限もありません(エは誤り)。


問題 5 (トランザクション)

データベースにおけるトランザクションの最も基本的な性質は何か。

ア. 一連の処理は必ず複数のSQL文で構成される。
イ. 処理の途中でも他のユーザーから変更結果が見える。
ウ. 一連の処理は全て成功するか、全て失敗して元の状態に戻るかのどちらかである。
エ. SELECT文だけがトランザクションの対象となる。

解答と解説

解答: ウ

解説:
トランザクションの原子性(Atomicity)とは、一連の処理が不可分な一つの単位として扱われ、全て実行されるか、全て実行されないかのどちらかであることを意味します。


問題 6 (ACID特性)

トランザクションのACID特性のうち、一度コミットされた変更は、システム障害が発生しても失われることなく永続的に保存されることを保証する特性は何か。

ア. 原子性 (Atomicity)
イ. 一貫性 (Consistency)
ウ. 独立性 (Isolation)
エ. 永続性 (Durability)

解答と解説

解答: エ

解説:
永続性(Durability)は、トランザクションが一度コミットされると、その結果は恒久的なものとなり、システム障害が発生しても失われることはない、という特性です。通常、これはログファイルへの書き込みによって保証されます。


問題 7 (MVCC)

MVCC (Multi-Version Concurrency Control) が主に解決しようとするデータベースの課題は何か。簡潔に説明しなさい。

解答と解説

解答:
読み取りと書き込みの競合を減らし、データベースの同時実行性を高めることです。MVCCでは、データ更新時に新しいバージョンを作成することで、読み取りトランザクションが更新中のデータによってブロックされるのを防ぎます。


問題 8 (排他制御 - ロックの種類)

データベースの排他制御において、あるデータに専有ロック(Xロック)がかかっている場合、他のトランザクションはそのデータに対してどのような操作が可能か。

ア. 読み取りと書き込みの両方が可能。
イ. 読み取りのみ可能。
ウ. 書き込みのみ可能。
エ. 読み取りも書き込みも不可能。

解答と解説

解答: エ

解説:
専有ロック(Xロック)は最も強力なロックであり、対象のデータへの他のトランザクションからの全てのアクセス(読み取り、書き込み)を排他します。これにより、データの一貫性が保たれます。


問題 9 (デッドロック)

デッドロックの発生を回避するための一つの方法として、「複数のデータにロックをかける必要がある場合、全てのトランザクションで同じ順序でロックをかける」というものがある。この方法が有効である理由を簡潔に説明しなさい。

解答と解説

解答:
ロックの獲得順序を統一することで、互いに相手がロックしている資源の解放を待ち合うという循環待機状態(デッドロックの必要条件の一つ)が発生するのを防ぐことができるためです。


問題 10 (分離レベル - ダーティリード)

ダーティリード(Dirty Read)とは、どのような現象か。簡潔に説明しなさい。

解答と解説

解答:
ダーティリードとは、あるトランザクション(T1)が、まだコミットされていない(ロールバックされる可能性がある)他のトランザクション(T2)によって変更されたデータを読み取ってしまう現象です。もしT2がロールバックされた場合、T1は存在しないはずのデータを読み取ったことになり、データの不整合を招きます。


問題 11 (分離レベル - ノンリピータブルリード)

READ COMMITTED分離レベルでは防ぐことができるが、REPEATABLE READ分離レベルでは防ぐことができる現象は何か。

ア. ダーティリード
イ. ノンリピータブルリード
ウ. ファントムリード
エ. デッドロック

解答と解説

解答: イ

解説:
READ COMMITTEDはダーティリードを防ぎますが、ノンリピータブルリード(同じデータを複数回読み取ったときに値が変わる現象)は防げません。REPEATABLE READはダーティリードとノンリピータブルリードの両方を防ぎます。ファントムリードはSERIALIZABLEのみが防ぎます。


問題 12 (チェックポイント)

データベースの障害回復において、チェックポイント処理の主な目的は何か。

ア. データベースの完全なバックアップを作成するため。
イ. トランザクションログに記録された全ての情報をディスクに書き出すため。
ウ. 障害発生時の復旧にかかる時間を短縮するため。
エ. ユーザーが手動でデータベースの状態を保存するため。

解答と解説

解答: ウ

解説:
チェックポイントは、メモリ上のバッファキャッシュにある変更されたデータをディスクに強制的に書き出す処理です。これにより、障害発生時にチェックポイント以降のログだけを処理すればよくなるため、復旧にかかる時間を短縮できます。


問題 13 (障害回復)

データベースの障害回復において、まだコミットされていない変更をログ情報に基づいて取り消し、トランザクション開始前の状態に戻す処理を何と呼ぶか。

ア. ロールフォワード (Roll-Forward)
イ. ロールバック (Roll-Back)
ウ. コミット (Commit)
エ. チェックポイント (Checkpoint)

解答と解説

解答: イ

解説:
ロールバック(Roll-Back)は、未コミットのトランザクションによる変更をログ(UNDO情報)に基づいて取り消し、データベースをトランザクション開始前の状態に戻す処理です。ロールフォワードはコミット済みの変更を再度適用する処理です。


問題 14 (NoSQL登場の背景)

NoSQLデータベースが登場した主な背景として、適切でないものはどれか。

ア. 膨大な量の非構造化データの処理要求。
イ. 水平スケーラビリティの実現の容易さへの要求。
ウ. 厳格なACID特性の全てを常に必要とするアプリケーションが増加したため。
エ. 柔軟なスキーマを持つデータモデルへの要求。

解答と解説

解答: ウ

解説:
NoSQLは、RDBMSが提供する厳格なACID特性を緩和することで、高い可用性やスケーラビリティ、パフォーマンス、柔軟なスキーマを実現しました。したがって、厳格なACID特性を必要とするアプリケーションが増加したことがNoSQLの背景ではありません。


問題 15 (NoSQLの種類)

JSONやBSONのようなドキュメント形式でデータを格納し、柔軟なスキーマを持つNoSQLデータベースのカテゴリは何か。

ア. Key-Value Store
イ. Document Store
ウ. Column-Family Store
エ. Graph Database

解答と解説

解答: イ

解説:
Document Store(ドキュメント指向データベース)は、JSONやBSON形式のドキュメントとしてデータを格納します。MongoDBなどが代表例です。


問題 16 (分散データベースのメリット)

分散データベースシステムの利点として、適切でないものはどれか。

ア. システムの水平スケーラビリティを高めることができる。
イ. データの局所性を高め、アクセス速度を向上させることができる。
ウ. 障害発生時のデータ復旧プロセスが常に単一のデータベースより単純になる。
エ. 特定のノードに障害が発生しても、システム全体の可用性を維持しやすい。

解答と解説

解答: ウ

解説:
分散データベースでは、データが複数のノードに分散しているため、障害発生時のデータ復旧や整合性維持のプロセスは、単一のデータベースよりもはるかに複雑になります。ア、イ、エは分散データベースの主な利点です。


問題 17 (CAP定理)

分散データベースシステムにおいて、CAP定理が示す3つの特性(Consistency, Availability, Partition tolerance)をすべて同時に満たすことはできない。この定理が意味する「Partition tolerance (分断耐性)」とは何か。

解答と解説

解答:
ネットワーク分断(一部のノード間での通信が途絶える状態)が発生しても、システム全体が停止することなく、動作を継続できる能力のことです。分散システムではネットワーク分断が必ず発生しうるため、分断耐性は必須の特性とされます。


問題 18 (カバリングインデックス)

カバリングインデックス(Covering Index / 包含インデックス)とはどのような索引か。そのメリットと共に簡潔に説明しなさい。

解答と解説

解答:
カバリングインデックスとは、問合せに必要な全てのカラムが索引自体に含まれている索引のことです。これにより、問合せの実行時にテーブル本体にアクセスする必要がなくなり、索引だけで結果を返せるため、I/Oが削減され、パフォーマンスが大幅に向上します。


問題 19 (REDOログとUNDOログ)

データベースのログファイルには、主にREDO情報とUNDO情報が記録されている。それぞれの役割について簡潔に説明しなさい。

解答と解説

解答:


問題 20 (直列化可能性と同時実行性)

トランザクションの独立性レベルで最も高いSERIALIZABLE(直列化可能)を選択した場合、データの整合性は最大限に保証されるが、その代償としてトレードオフになる要素は何か。

ア. ストレージ消費量
イ. ネットワーク遅延
ウ. 同時実行性
エ. 開発の複雑さ

解答と解説

解答: ウ

解説:
SERIALIZABLEレベルは、最も厳格な分離を提供するため、他のトランザクションとの競合を避けるために強力なロックを多用します。これにより、トランザクション間の待機が増え、同時に実行できるトランザクションの数が減るため、同時実行性が低下する可能性があります。

第3章 設計

3.1 概念設計

データベース設計は、システムの要件を分析し、最適なデータベース構造を構築するプロセスです。このプロセスは通常、以下の3つのフェーズで進められます。

  1. 概念設計 (Conceptual Design): ユーザーの視点から、現実世界の情報を抽象化してデータモデルを作成する。
  2. 論理設計 (Logical Design): 概念設計で作成したモデルを、特定のリレーショナルデータベースモデルに変換する。
  3. 物理設計 (Physical Design): 論理設計で作成したモデルを、特定のDBMSの特性に合わせて物理的な格納構造を定義する。

概念設計は、データベース設計の最初のステップであり、最も重要なフェーズの一つです。ここでは、特定のデータベースシステム(DBMS)の種類や物理的な実装方法に依存せず、ビジネス要件やユーザーの視点から、必要なデータとその関連性を洗い出し、明確に定義することを目的とします。

目的

成果物

概念設計の主要な成果物は、**E-R図(Entity-Relationship Diagram)**です。E-R図は、エンティティ、属性、リレーションシップをグラフィカルに表現したもので、データベースの「青写真」となります。

概念設計をしっかりと行うことで、後続の論理設計や物理設計がスムーズに進み、システムの要件漏れやデータ不整合を防ぐことができます。

3.1.1 E-R図

**E-R図(Entity-Relationship Diagram: エンティティ関連図)**は、データベースの概念設計において、現実世界に存在する「モノ」や「コト」、それらの「属性」、そして「モノ」や「コト」同士の「関係」を視覚的に表現するための図法です。

E-R図にはいくつかの表記法がありますが、ここでは代表的な要素とその表現方法を紹介します。

E-R図の主要な構成要素

  1. エンティティ (Entity: 実体)

  2. 属性 (Attribute: 特徴)

  3. リレーションシップ (Relationship: 関係)

  4. 多重度 (Cardinality: カーディナリティ)

E-R図の例 (Mermaid形式)

顧客が製品を注文し、その注文は複数の製品で構成される場合のE-R図をMermaid形式で表現します。

erDiagram CUSTOMER ||--o{ ORDER : "places" ORDER ||--o{ ORDER_DETAIL : "includes" PRODUCT ||--o{ ORDER_DETAIL : "is_part_of" CUSTOMER { int customer_id PK string customer_name string address string phone_number } ORDER { int order_id PK int customer_id FK date order_date string status } PRODUCT { int product_id PK string product_name decimal price int stock_quantity } ORDER_DETAIL { int order_id PK, FK int product_id PK, FK int quantity decimal unit_price }

図の解説:

このE-R図は、データベースに格納すべき情報とその関係性を、誰にでも分かりやすい形で視覚化するのに役立ちます。


3.1.2 エンティティ

**エンティティ(実体)**は、E-R図を構成する最も基本的な要素であり、現実世界における「識別可能な独立したモノやコト」を表します。データベースでは、このエンティティが「テーブル」に対応します。

エンティティの特定方法

ビジネス要件やシステム化の対象となる業務を分析する際、以下の点に着目するとエンティティを特定しやすくなります。

エンティティの分類

エンティティは、その性質によっていくつかの種類に分類できます。

  1. 独立エンティティ(主エンティティ):

  2. 従属エンティティ(弱エンティティ):

  3. 関連エンティティ(連関エンティティ):

主キー (Primary Key) の選定

エンティティの各インスタンスを一意に識別するための属性または属性の組み合わせを主キーと呼びます。主キーの選定は、データベースの整合性と効率に大きく影響します。

主キーには、現実世界の意味を持つ自然キー(例: 顧客コード、ISBNコード)と、システムが内部的に生成する意味を持たない代理キー(サロゲートキー)(例: 連番のID)があります。 実務では、変更の可能性が低い連番などの代理キーを主キーとし、業務上の識別子をUNIQUE制約付きの候補キーとすることが推奨されることが多いです。

3.1.3 リレーションシップ

**リレーションシップ(関係)**は、E-R図において、エンティティ間に存在する論理的なつながりや相互作用を示します。このリレーションシップが、データベースにおけるテーブル間の関連性(FOREIGN KEY)に変換されます。

リレーションシップの特定方法

リレーションシップの多重度(カーディナリティ)

多重度は、リレーションシップの両端において、一方のエンティティの1つのインスタンスが、もう一方のエンティティのいくつのインスタンスと関連を持つことができるかを示します。これは、E-R図で最も重要な情報の1つです。

  1. 1対1 (One-to-One: 1:1)

  2. 1対多 (One-to-Many: 1:N)

  3. 多対多 (Many-to-Many: N:M)

参加の任意性(Optionality)

多重度と合わせて、リレーションシップの参加が必須(Mandatory)か任意(Optional)かも表現します。


3.2 論理設計

論理設計は、概念設計で作成したE-R図などの概念データモデルを、特定のリレーショナルデータベースの枠組み(リレーショナルモデル)に変換するフェーズです。この段階では、まだ特定のDBMS製品(Oracle, PostgreSQLなど)の具体的な機能には依存しませんが、リレーショナルデータベースの基本的な制約や特性を考慮に入れます。

目的

成果物

論理設計は、データベースの長期的な安定性とパフォーマンスに直結する重要なフェーズです。特に「正規化」は、データベーススペシャリスト試験において頻出のテーマであり、深く理解する必要があります。

3.2.1 関係スキーマ

**関係スキーマ(Relational Schema)**は、リレーショナルデータベースのテーブルの構造を形式的に記述したものです。論理設計の主要な成果物の一つであり、エンティティがテーブル、属性がカラム、リレーションシップが外部キーとして表現されます。

記述形式

一般的に、以下のような形式で記述されます。

テーブル名 (主キー, 属性1, 属性2, ..., 外部キー1, 外部キー2, ...)

E-R図から関係スキーマへの変換例

E-R図の例で示したCUSTOMER, ORDER, PRODUCT, ORDER_DETAILエンティティを関係スキーマに変換してみましょう。

  1. CUSTOMERエンティティ:

  2. PRODUCTエンティティ:

  3. ORDERエンティティ:

  4. ORDER_DETAILエンティティ:

このように、E-R図で表現された概念が、リレーショナルモデルの具体的なテーブル構造として定義されます。

3.2.2 関数従属

**関数従属(Functional Dependency: FD)**は、リレーショナルデータベースの正規化を理解する上で最も重要な概念の一つです。

「属性集合Xが属性集合Yを関数従属する」とは、X -> Yと表記され、属性集合Xの値が一意に決まれば、属性集合Yの値も一意に決まるという関係を意味します。

関数従属の性質

関数従属は、テーブル内の属性間の論理的な関係を示しており、この関係を分析することで、データの冗長性や更新時の異常(アノマリ)の原因を特定し、正規化へとつなげていきます。

3.2.3 完全/部分関数従属

関数従属には、主キーとの関係によって完全関数従属部分関数従属があります。これらは第2正規形(2NF)を理解する上で重要な概念です。

完全関数従属 (Full Functional Dependency)

属性集合Yが属性集合Xに完全関数従属するとは、X -> Y であり、かつXのどの真部分集合(Xの一部)もYを関数従属しない場合をいいます。

: 注文明細テーブル ORDER_DETAIL (注文ID PK, 製品ID PK, 数量, 単価) 複合主キーは(注文ID, 製品ID)

部分関数従属 (Partial Functional Dependency)

属性集合Yが属性集合Xに部分関数従属するとは、X -> Y であり、かつXの真部分集合(Xの一部)がYを関数従属する場合をいいます。部分関数従属は、第2正規形(2NF)の違反の原因となります。

: 注文明細テーブル(製品名を含めてしまった場合) ORDER_DETAIL (注文ID PK, 製品ID PK, 数量, 単価, 製品名) 複合主キーは(注文ID, 製品ID)

このような部分関数従属があると、データに以下のような問題(更新異常)が生じます。

3.2.4 推移的関数従属

**推移的関数従属(Transitive Functional Dependency)**は、第3正規形(3NF)を理解する上で重要な概念です。

属性集合X、Y、Zが存在し、X -> Y かつ Y -> Z であり、かつYがXの真部分集合ではなく、Yが候補キーではない場合に、ZXに推移的に関数従属するといいます。

より平易に言えば、主キーではない属性を介して、他の非主キー属性が主キーに従属している状態です。

: 従業員テーブル EMPLOYEE (社員ID PK, 社員氏名, 部署ID FK, 部署名, 部署所在地) 主キーは社員ID

関数従属の関係は以下のようになります。

この場合、社員ID -> 部署ID かつ 部署ID -> 部署名 の関係があるため、部署名社員ID推移的に関数従属しています。 同様に、部署所在地社員ID推移的に関数従属しています。

このような推移的関数従属があると、データに以下のような問題(更新異常)が生じます。

推移的関数従属は、第3正規形(3NF)への正規化によって解消されます。

3.2.5 アームストロングの公理

**アームストロングの公理(Armstrong's Axioms)**は、リレーショナルデータベースにおける関数従属の性質を形式的に記述した一連の規則です。これらの公理を使うことで、ある関数従属の集合から、それに含まれる全ての関数従属を導き出すことができます。

アームストロングの公理は以下の3つの規則(推論規則)から構成されます。

  1. 反射律 (Reflexivity)

  2. 増加律 (Augmentation)

  3. 推移律 (Transitivity)

これらの3つの公理は「健全(Sound)」であり「完全(Complete)」であることが証明されています。つまり、これらの公理を使って導出される全ての関数従属は正しいものであり、また、正しい全ての関数従属を導出することができます。

アームストロングの公理は、正規化のプロセスで複雑な関数従属関係を分析し、テーブルの分解が必要かどうかを判断するための理論的な基盤を提供します。

3.2.6 正規化

**正規化(Normalization)**は、リレーショナルデータベース設計において、データの冗長性(重複)を排除し、データの整合性(一貫性)を保ち、データ操作時(挿入、更新、削除)に発生する不整合(異常: アノマリ)を防ぐために、テーブルの構造を整理(分解)する体系的なプロセスです。

正規化の目的

  1. データの冗長性の排除:
  2. 更新・挿入・削除異常の防止:
  3. データ整合性の向上:
  4. データモデルの明確化と理解の容易さ:

正規化のプロセス

正規化は、いくつかの段階(正規形)を経て行われます。最も基本的な第1正規形から始まり、段階的に厳しくなる条件を満たすようにテーブルを分解していきます。一般的には、第3正規形(3NF)まで達成されていれば、多くのビジネスアプリケーションで十分な整合性が確保されるとされています。

この後のセクションで、各正規形とその特徴、正規化の方法について詳しく見ていきます。

3.2.7 第1正規形 (1NF)

**第1正規形(First Normal Form: 1NF)**は、正規化の最も基本的な段階です。

定義

テーブルが第1正規形であるための条件は以下の通りです。

  1. 繰り返しグループがないこと(繰り返し属性がないこと):
  2. 全ての属性が原子値であること(非原子属性がないこと):

第1正規形ではない例

顧客ID 顧客名 電話番号1 電話番号2 電話番号3
101 山田太郎 090-XXXX-1111 03-YYYY-2222
102 佐藤花子 090-XXXX-3333

このテーブルは、電話番号が繰り返しグループとして存在するため、第1正規形ではありません。

第1正規形への変換

繰り返しグループや非原子属性を解消するために、以下のいずれかの方法でテーブルを分解します。

  1. 新しいテーブルとして分離する: 繰り返しグループを新しいテーブルとして分離し、元のテーブルの主キーを外部キーとして持たせる。
  2. 複合主キーにする: 繰り返しグループを形成する属性と、元のテーブルの主キーを組み合わせて新しい主キーとする。

上記の例を第1正規形に変換する:

新しい顧客電話番号テーブルを分離する方法。

顧客ID 顧客名
101 山田太郎
102 佐藤花子
顧客ID 電話番号
101 090-XXXX-1111
101 03-YYYY-2222
102 090-XXXX-3333

このように分解することで、データの追加、更新、削除が容易になり、冗長性が低減します。

3.2.8 第2正規形 (2NF)

**第2正規形(Second Normal Form: 2NF)**は、第1正規形よりもさらに冗長性を排除するための段階です。

定義

テーブルが第2正規形であるための条件は以下の通りです。

  1. 第1正規形であること。
  2. 全ての非キー属性が、主キーに完全に関数従属していること。

第2正規形ではない例

注文明細と製品情報が一緒になったテーブルを考えます。 ORDER_DETAIL_PRODUCT (注文ID PK, 製品ID PK, 数量, 単価, 製品名, 製品説明)

主キーは複合主キー(注文ID, 製品ID)です。 ここで、以下の関数従属を考えます。

製品名製品説明は、複合主キー(注文ID, 製品ID)全体ではなく、その一部である製品IDにのみ関数従属しています。これは部分関数従属であり、このテーブルは第2正規形ではありません。

第2正規形ではないことによる問題(更新異常)

第2正規形への変換

部分関数従属が存在する場合、その部分関数従属を形成している属性(主キーの一部と、それに従属する非キー属性)を新しいテーブルとして分離します。

上記の例を第2正規形に変換する:

製品テーブルの主キー製品IDは、注文明細テーブルでは外部キーとして参照されます。 このように分解することで、データの重複が排除され、更新異常などの問題が解消されます。

3.2.9 第3正規形 (3NF)

**第3正規形(Third Normal Form: 3NF)**は、第2正規形よりもさらに冗長性を排除するための段階です。多くの実用的なデータベース設計では、第3正規形が目標とされます。

定義

テーブルが第3正規形であるための条件は以下の通りです。

  1. 第2正規形であること。
  2. 非キー属性が、主キーに対して推移的に関数従属していないこと。

第3正規形ではない例

第2正規形を満たしているが、第3正規形ではない従業員テーブルを考えます。 EMPLOYEE (社員ID PK, 社員氏名, 部署ID FK, 部署名, 部署所在地)

主キーは社員ID。 ここで、以下の関数従属を考えます。

部署名部署所在地は、主キー社員IDに直接従属しているのではなく、非キー属性である部署IDを介して従属しています(社員ID -> 部署ID -> 部署名)。これは推移的関数従属であり、このテーブルは第3正規形ではありません。

第3正規形ではないことによる問題(更新異常)

第3正規形への変換

推移的関数従属が存在する場合、その推移的関数従属を形成している属性(非キー属性と、それに従属する非キー属性)を新しいテーブルとして分離します。

上記の例を第3正規形に変換する:

部署テーブルの主キー部署IDは、従業員テーブルでは外部キーとして参照されます。 このように分解することで、データの重複が排除され、更新異常などの問題が解消されます。

3.2.10 その他の正規化

第3正規形までがデータベース設計で一般的に目指される正規化のレベルですが、さらに高度な正規形も存在します。これらは特定の状況下でのみ考慮されることが多く、実務では3NFが達成されていれば十分とされることが多いです。

  1. ボイス・コッド正規形 (Boyce-Codd Normal Form: BCNF)

  2. 第4正規形 (Fourth Normal Form: 4NF)

  3. 第5正規形 (Fifth Normal Form: 5NF)

正規化のメリットとデメリット

このため、実務では、パフォーマンスと整合性のバランスを取り、**意図的に非正規化(Denormalization)**を行うこともあります。これは、通常、読取性能の向上を目的として、更新異常のリスクを許容しながら冗長なデータをあえて持たせる設計手法です。しかし、非正規化は慎重に、そしてリスクを理解した上で行うべきです。


第3章 設計 問題集 (20問)


問題 1 (概念設計の目的)

データベース設計における概念設計の主な目的として、最も適切なものはどれか。

ア. 特定のDBMSの物理的な記憶構造を定義すること。
イ. ビジネス要件から必要なデータとその関連性を抽出し、DBMSに依存しないデータモデルを作成すること。
ウ. SQL文のパフォーマンスを最大化するためのインデックスを設計すること。
エ. 既存のテーブルを統合し、データ冗長性を意図的に増やすこと。

解答と解説

解答: イ

解説:
概念設計は、データベース設計の最初のフェーズであり、ユーザーの視点から現実世界の情報を抽象化してデータモデルを作成します。特定のDBMSに依存せず、ビジネス要件を正確に反映したデータ構造を定義することが目的です。


問題 2 (E-R図の要素)

E-R図において、エンティティ(実体)を表すために一般的に使用される記号はどれか。

ア. ひし形(菱形)
イ. 楕円形
ウ. 長方形
エ. 矢印

解答と解説

解答: ウ

解説:
E-R図の一般的な表記法では、エンティティは長方形で、属性は楕円形で、リレーションシップはひし形で表されます。


問題 3 (多重度 - 1対多)

「1つの部署には複数の従業員が所属するが、1人の従業員は1つの部署にだけ所属する」という関係の多重度(カーディナリティ)は何か。

ア. 1対1 (One-to-One)
イ. 1対多 (One-to-Many)
ウ. 多対多 (Many-to-Many)
エ. 多対1 (Many-to-One)

解答と解説

解答: イ

解説:
この関係は、部署側から見れば「1つの部署に複数の従業員」なので「多」、従業員側から見れば「1人の従業員は1つの部署」なので「1」です。したがって「1対多」の関係となります。


問題 4 (リレーションシップのデータベース表現)

E-R図で表現された「1対多」のリレーションシップをリレーショナルデータベースで表現する際、一般的にどのような方法がとられるか。

ア. 独立した関連テーブルを作成する。
イ. 「多」側のテーブルに「1」側のテーブルの主キーを外部キーとして持たせる。
ウ. 「1」側のテーブルに「多」側のテーブルの主キーを外部キーとして持たせる。
エ. 両方のテーブルを統合し、単一のテーブルとする。

解答と解説

解答: イ

解説:
1対多の関係では、「多」側のエンティティ(例えば従業員)が「1」側のエンティティ(例えば部署)の主キーを外部キーとして持つことで、関連を表現します。


問題 5 (論理設計の目的)

データベース設計における論理設計の主な目的として、最も適切なものはどれか。

ア. 業務要件を抽出し、E-R図を作成すること。
イ. 特定のDBMS製品を選択し、その設定を行うこと。
ウ. 関係スキーマを定義し、データの冗長性を排除すること。
エ. ディスク容量やアクセス方法などの物理的な側面を考慮すること。

解答と解説

解答: ウ

解説:
論理設計は、概念設計で作成したE-R図をリレーショナルモデルに変換し、正規化を通じてデータの冗長性を排除し、整合性を確保することが主な目的です。


問題 6 (関数従属)

「属性集合Xの値が一意に決まれば、属性集合Yの値も一意に決まる」という関係を何と呼ぶか。

ア. 多値従属
イ. 結合従属
ウ. 関数従属
エ. 候補キー

解答と解説

解答: ウ

解説:
この定義は関数従属(Functional Dependency)そのものです。X -> Yと表記されます。


問題 7 (部分関数従属)

以下のORDER_DETAIL_PRODUCTテーブルを考える。

ORDER_DETAIL_PRODUCT (注文ID PK, 製品ID PK, 数量, 単価, 製品名, 製品説明)

このテーブルの主キーは(注文ID, 製品ID)である。このテーブルにおいて、第2正規形(2NF)に違反する原因となる「部分関数従属」の例として最も適切なものはどれか。

ア. 注文ID -> 数量
イ. (注文ID, 製品ID) -> 単価
ウ. 製品ID -> 製品名
エ. 注文ID -> 製品名

解答と解説

解答: ウ

解説:
部分関数従属とは、複合主キーの一部に非キー属性が関数従属している状態です。 製品名は主キー全体(注文ID, 製品ID)ではなく、主キーの一部である製品IDのみに決定されます(製品ID -> 製品名)。これは部分関数従属です。


問題 8 (推移的関数従属)

以下のEMPLOYEEテーブルを考える。

EMPLOYEE (社員ID PK, 社員氏名, 部署ID FK, 部署名)

このテーブルの主キーは社員IDである。このテーブルにおいて、第3正規形(3NF)に違反する原因となる「推移的関数従属」の例として最も適切なものはどれか。

ア. 社員ID -> 社員氏名
イ. 部署ID -> 部署名
ウ. 社員ID -> 部署名
エ. 社員ID -> 部署ID

解答と解説

解答: ウ

解説:
推移的関数従属とは、主キーではない属性を介して、他の非主キー属性が主キーに従属している状態です。この場合、社員ID -> 部署ID かつ 部署ID -> 部署名 の関係があるため、部署名社員IDに推移的に関数従属しています。


問題 9 (アームストロングの公理)

アームストロングの公理のうち、「もしX -> Yであり、かつY -> Zであるならば、X -> Zである」と述べられている規則は何か。

ア. 反射律 (Reflexivity)
イ. 増加律 (Augmentation)
ウ. 推移律 (Transitivity)
エ. 分解律 (Decomposition)

解答と解説

解答: ウ

解説:
これはアームストロングの公理の推移律です。関数従属が連鎖的に発生することを示しています。


問題 10 (正規化の目的)

データベースの正規化を行う主な目的として、最も適切でないものはどれか。

ア. データの冗長性を排除するため。
イ. 更新・挿入・削除異常を防止するため。
ウ. データベースの物理的なアクセス速度を必ず向上させるため。
エ. データ整合性を確保し、データモデルを明確にするため。

解答と解説

解答: ウ

解説:
正規化の主要な目的はデータの冗長性排除と整合性確保です。正規化によってテーブルが分解され、結合操作が増えることで、むしろ物理的なアクセス速度(パフォーマンス)が低下する可能性もあります。そのため、意図的に非正規化を行うこともあります。


問題 11 (第1正規形)

テーブルが第1正規形(1NF)であるための条件は何か。簡潔に説明しなさい。

解答と解説

解答:
繰り返しグループ(繰り返し属性)がないこと、および全ての属性が原子値(それ以上分割できない最小単位)であることです。つまり、1つのセルには単一の不可分な値のみが格納されている状態を指します。


問題 12 (第2正規形への変換)

以下の学生履修テーブルは第1正規形を満たしているが、第2正規形ではない。これを第2正規形に変換する際、どのようにテーブルを分解すべきか。

STUDENT_COURSE (学生ID PK, 科目ID PK, 学生氏名, 科目名, 履修日)

解答と解説

解答:
このテーブルには以下の部分関数従属が存在する。

これらを解消するために、テーブルを以下のように分解する。


問題 13 (第3正規形への変換)

以下の社員テーブルは第2正規形を満たしているが、第3正規形ではない。これを第3正規形に変換する際、どのようにテーブルを分解すべきか。

EMPLOYEE (社員ID PK, 社員氏名, 部署ID FK, 部署名, 部署所在地)

解答と解説

解答:
このテーブルには以下の推移的関数従属が存在する。

これらを解消するために、テーブルを以下のように分解する。


問題 14 (正規化のメリット)

正規化を進めることによって得られるメリットを2つ挙げなさい。

解答と解説

解答例:

  1. データの冗長性排除: データが重複して格納されることを防ぎ、記憶領域を節約し、データの整合性を維持しやすくなる。
  2. 更新・挿入・削除異常の防止: データ操作時に発生する矛盾や情報消失のリスクを低減する。
  3. データ整合性の向上: 一貫性のある正確なデータを保ちやすくなる。
  4. データモデルの明確化: 各テーブルの役割が明確になり、データベース構造が理解しやすくなる。

問題 15 (非正規化)

データベースの**非正規化(Denormalization)**とは何か。その主な目的も合わせて簡潔に説明しなさい。

解答と解説

解答:
非正規化とは、正規化されたデータベースのテーブルを、意図的に冗長な形に戻したり、テーブルを結合したりする設計手法です。主な目的は、結合操作の回数を減らすことで、特に読み取り性能(クエリのパフォーマンス)を向上させることです。データの整合性維持が難しくなるというデメリットがあります。


問題 16 (候補キー)

テーブル内の属性(カラム)または属性の集合で、行を一意に識別できる最小のものを何と呼ぶか。

ア. 主キー (Primary Key)
イ. 外部キー (Foreign Key)
ウ. 候補キー (Candidate Key)
エ. 副キー (Alternate Key)

解答と解説

解答: ウ

解説:
候補キーは、テーブル内の行を一意に識別できる属性(または属性の集合)で、それ以上属性を減らすと一意性を失う「最小の」ものです。主キーはその候補キーの中から一つ選ばれたものです。


問題 17 (多対多のリレーションシップ)

E-R図において「多対多」のリレーションシップが存在する場合、論理設計でリレーショナルスキーマに変換する際、どのように表現されるか。

解答と解説

解答:
「多対多」のリレーションシップは、直接リレーショナルスキーマに変換できないため、間に**関連エンティティ(連関エンティティ)**を導入し、それを新しいテーブルとして表現します。この関連エンティティは、元の2つのエンティティの主キーを外部キーとして持ち、それらを複合主キーとすることが一般的です。


問題 18 (E-R図の属性)

E-R図で属性(Attribute)を表すために使用される記号は何か。また、主キーとなる属性を表す際の一般的な慣習も合わせて述べなさい。

解答と解説

解答:
属性は一般的に楕円形で表されます。簡略化されたE-R図では、エンティティの長方形の中に直接属性名を列挙することもあります。主キーとなる属性を表す際は、属性名に下線を引くのが一般的な慣習です。


問題 19 (論理設計と物理設計の違い)

論理設計と物理設計の主な違いは何か。簡潔に説明しなさい。

解答と解説

解答:
論理設計は、概念設計の成果物をリレーショナルモデルに変換し、正規化を通じてデータの冗長性を排除するフェーズで、特定のDBMSに依存しない。一方、物理設計は、論理設計の成果物を基に、選択したDBMSの特性(インデックス、パーティショニング、記憶域パラメータなど)を考慮し、物理的なデータの格納方法やアクセス方法を具体的に決定するフェーズである。


問題 20 (第3正規形の定義)

テーブルが第3正規形(3NF)であるための条件を2つ挙げなさい。

解答と解説

解答:

  1. 第2正規形であること。
  2. 非キー属性が、主キーに対して推移的に関数従属していないこと。 (つまり、非キー属性が他の非キー属性を介して主キーに従属する状態がないこと。)

第4章 午後試験対策 物理設計

4.1 索引

第2章で、索引(インデックス)はデータベースの検索性能を向上させるために不可欠な要素であると学びました。物理設計のフェーズでは、この索引をどのように設計し、実装すれば、アプリケーションの性能要件を満たせるかを具体的に検討します。

午後試験では、与えられた業務要件やSQLの実行計画(EXPLAINの結果など)を分析し、最適な索引を提案する問題が頻繁に出題されます。ここでは、特に試験で問われやすい索引の設計と、その利用条件について深く掘り下げていきます。

4.1.1 複合索引

複合索引とは、複数のカラム(列)を組み合わせて作成される索引のことです。単一のカラムに作成される索引よりも、特定の種類のクエリにおいて高い効果を発揮します。

列の順序が重要(前方一致の原則)

複合索引の設計で最も重要なのは、索引を構成するカラムの順序です。この順序によって、索引が利用できるクエリの範囲が大きく変わります。

複合索引は、その構成カラムの先頭から連続した部分に対して前方一致で利用されます。これを**前方一致の原則(Left-most Prefix Rule)**と呼びます。

例えば、Productsテーブルに(category_id, product_name, price)という複合索引を作成した場合を考えます。

CREATE INDEX idx_products_cat_name_price ON Products (category_id, product_name, price);

この索引は、以下の条件を持つクエリで利用可能です。

  1. WHERE category_id = ? (先頭カラムのみ)
  2. WHERE category_id = ? AND product_name = ? (先頭2カラム)
  3. WHERE category_id = ? AND product_name = ? AND price = ? (全カラム)

一方、以下の条件を持つクエリでは、この複合索引は利用されないか、限定的にしか利用されません

複合索引の活用例

午後試験対策のポイント

午後試験では、以下のような形で複合索引の知識が問われることが多いです。

単に「索引を作成する」だけでなく、「どのような索引を、なぜ、どの順序で作成するのか」を明確に説明できるようになることが重要です。


4.1.2 使用されない索引

索引はデータベースの検索性能を向上させる強力なツールですが、常に利用されるわけではありません。間違った設計や条件の指定方法により、せっかく作成した索引がデータベースから利用されず、フルテーブルスキャンが発生して性能問題を引き起こすことがあります。

索引が使用されない主な原因

  1. 前方一致の原則の不遵守:

  2. インデックスのカーディナリティが低い場合:

  3. テーブルのデータ量が少ない場合:

  4. OR条件での結合:


4.1.3 索引が使用されないその他の条件

複合索引の順序の他に、SQLの記述方法やデータ型によっても索引が利用されないことがあります。

  1. 索引カラムへの関数適用:

  2. データ型の不一致:

  3. NOT演算子の使用:

  4. ワイルドカード(%_)を先頭に使用したLIKE検索:

  5. オプティマイザの統計情報が古い:


4.1.4 クラスタ率

**クラスタ率(Clustering Factor)**とは、テーブルの物理的な格納順序が、特定の索引の論理的な順序とどの程度一致しているかを示す指標です。索引の効率性、特に範囲検索の性能に大きく影響します。

クラスタ率が高い場合

クラスタ率が低い場合

Ordersテーブルに(order_date)という索引があり、物理的なデータもorder_date順に格納されていればクラスタ率は高いです。 しかし、Ordersテーブルがcustomer_id順に物理的に格納されている場合、order_date索引に対するクラスタ率は低くなります。order_dateの範囲検索をすると、customer_idの異なる多くのブロックからデータを読み込む必要があるため、I/Oが増えます。

午後試験対策のポイント

午後試験では、「特定の索引のクラスタ率が低いことが原因で性能劣化が起きている」というシナリオが提示され、それを改善するための方法を問われることがあります。


4.2 表領域とページ

4.2.1 表領域 (Tablespace)

**表領域(Tablespace)**は、データベースにおける物理的な記憶領域を論理的に管理するための単位です。データベース全体をいくつかの表領域に分割し、それぞれの表領域を一つ以上のデータファイルに割り当てます。

表領域の役割

4.2.2 ページ (Page / Block)

ページ(Page)、または**ブロック(Block)**は、データベースにおけるディスクI/Oの最小単位です。データベースがディスクからデータを読み込む際や、ディスクにデータを書き込む際は、必ずこのページ単位で行われます。

ページの役割と構造

4.2.3 空き領域

データベースのページ内には、将来のデータ挿入や更新に備えて**空き領域(Free Space)**を確保しておくことが重要です。

空き領域の管理パラメータ (PCTFREE, PCTUSEDなど)

多くのDBMSでは、ページ内の空き領域を管理するためのパラメータを提供しています。

午後試験対策のポイント

午後試験では、PCTFREEPCTUSEDの値を調整することで、更新頻度の高いテーブルや挿入頻度の高いテーブルのI/O性能をどのように改善するか、といった形で問われることがあります。


4.3 区分化

区分化(Partitioning: パーティショニング)とは、非常に大きなテーブルや索引を、論理的または物理的に小さく分割し、管理しやすくする技術です。ユーザーからは一つのテーブルに見えますが、内部的には複数のパーティションに分割されています。

4.3.1 区分化の特徴

メリット

  1. パフォーマンス向上:
  2. 管理性向上:
  3. 可用性向上:

デメリット

  1. 設計の複雑化:
  2. グローバル索引の管理:

4.3.2 区分化の種類

区分化には、データをどのように分割するかに応じていくつかの種類があります。

  1. レンジ区分化 (Range Partitioning)

  2. リスト区分化 (List Partitioning)

  3. ハッシュ区分化 (Hash Partitioning)

  4. コンポジット区分化 (Composite Partitioning)

午後試験対策のポイント

午後試験では、大量データを扱うシステムの性能問題(例: 特定期間のデータ検索が遅い)や運用管理問題(例: 古いデータの削除に時間がかかる)が提示され、それを区分化によってどのように解決するかを問われることがあります。パーティションキーの選定理由や、パーティションの種類とメリット・デメリットを具体的に説明できるように準備しておきましょう。


4.4 共通テーブル式 (Common Table Expressions - CTEs)

**共通テーブル式(CTE)**は、WITH句を使用して定義する一時的な名前付き結果セットです。SELECT, INSERT, UPDATE, DELETE文の中で使用できます。CTEはクエリの読みやすさと保守性を向上させ、複雑なクエリを段階的に構築するのに役立ちます。

構文

WITH CTE名 AS ( SELECT ... ) SELECT ... FROM CTE名 WHERE ...;

メリット

  1. 可読性の向上: 複雑なクエリを複数の小さな論理的なステップに分割できます。
  2. 再利用性: 同じCTEを単一のクエリ内で複数回参照できます(ただし、通常は実際に複数回実行されるわけではありません)。
  3. 再帰クエリの実現: 階層構造のデータを扱う再帰CTEを定義できます。

-- 平均価格より高い製品を、共通テーブル式を使って検索 WITH AveragePrice AS ( SELECT AVG(price) AS avg_p FROM Products ) SELECT p.product_name, p.price FROM Products p, AveragePrice ap WHERE p.price > ap.avg_p;

午後試験対策のポイント

午後試験では、複雑な集計や階層構造のデータを扱うSQLの問題で、CTEを使った解答が求められたり、CTEの活用によるクエリの改善点を問われたりすることがあります。特に再帰CTEは、部品構成表などの問題で出題される可能性があります。


4.5 ウィンドウ関数

ウィンドウ関数は、SELECT文のOVER句と組み合わせて使用され、**現在の行に関連する行のグループ(ウィンドウ)**に対して集計や順位付けなどの計算を行うSQL関数です。GROUP BY句による集約と異なり、ウィンドウ関数は元の行を減らすことなく、各行に対して集計結果などを付加できるのが特徴です。

基本構文

ウィンドウ関数名 ([引数]) OVER ( [PARTITION BY カラム名, ...] -- ウィンドウ(グループ)の定義 [ORDER BY カラム名 [ASC|DESC], ...] -- ウィンドウ内の行の順序 [ROWS/RANGE BETWEEN ...] -- ウィンドウの範囲(オプション) )

4.5.1 区分ごとに平均値や合計値を計算する

PARTITION BY句を使うことで、特定のカラムの値に基づいて行を区分(パーティション)し、その区分ごとに集計関数を適用できます。

-- 各製品のカテゴリごとの平均価格を、製品ごとに表示 SELECT product_name, category_id, price, AVG(price) OVER (PARTITION BY category_id) AS avg_price_in_category FROM Products;

このクエリでは、category_idが同じ製品同士で平均価格を計算し、その結果を各製品の行に付加します。

4.5.2 前後の値を使って集計する

ROWS BETWEEN句を使うことで、ウィンドウ内の現在の行の前後の特定の範囲の行に対して集計を行うことができます。移動平均(Moving Average)の計算などに使われます。

-- 発売日順で、その製品と直近2つの製品の平均価格(3製品移動平均)を計算 SELECT release_date, product_name, price, AVG(price) OVER (ORDER BY release_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg_price FROM Products;

ROWS BETWEEN 2 PRECEDING AND CURRENT ROWは、現在の行とその前の2行(計3行)をウィンドウの範囲とします。

4.5.3 前(または後)の行を取得する

LAG()LEAD()関数を使うと、ウィンドウ内で指定した順序に基づき、現在の行の前の行後の行のカラム値を取得できます。時系列データの比較などに非常に便利です。

-- 発売日順で、前の製品の価格と現在の製品の価格の差を表示 SELECT release_date, product_name, price, LAG(price, 1, 0) OVER (ORDER BY release_date) AS previous_price, -- 1行前のprice、無ければ0 price - LAG(price, 1, 0) OVER (ORDER BY release_date) AS price_difference FROM Products;

4.5.4 順位を求める

RANK(), DENSE_RANK(), ROW_NUMBER()などの関数を使って、ウィンドウ内で順位を付けることができます。

-- 各カテゴリ内で価格の高い順に製品の順位を付ける SELECT product_name, category_id, price, RANK() OVER (PARTITION BY category_id ORDER BY price DESC) AS rank_in_category FROM Products;

4.5.5 所属する階級を求める

NTILE(n)関数は、ウィンドウ内の行をn個のグループに均等に分割し、各行がどのグループに属するかを示す番号を返します。

-- 全製品を価格でソートし、4つの階級に分ける SELECT product_name, price, NTILE(4) OVER (ORDER BY price DESC) AS price_quartile FROM Products;

午後試験対策のポイント

ウィンドウ関数は、複雑な集計や分析をSQL単体で記述できる強力な機能であり、午後試験でも非常に頻繁に出題されます。特に、「期間を指定した集計」「前後のデータとの比較」「順位付け」といった要件に対して、適切にウィンドウ関数を活用できるかが問われます。PARTITION BYORDER BYROWS BETWEENの組み合わせを理解し、使いこなすことが重要です。


4.6 トリガー

**トリガー(Trigger)**は、データベース内で特定のイベント(INSERT, UPDATE, DELETEなどのDML操作)が発生した際に、自動的に実行される特別なストアドプロシージャのようなものです。データの整合性保証や監査ログの記録など、様々な用途で利用されます。

基本的な構文

CREATE TRIGGER トリガー名 {BEFORE | AFTER} {INSERT | UPDATE | DELETE} ON テーブル名 [FOR EACH ROW] -- 各行に対して実行 (ROWトリガー) / ステートメント全体に対して実行 (STATEMENTトリガー) [WHEN 条件式] -- オプション: トリガーを起動する条件 BEGIN -- トリガーが実行されるSQL文や手続き END;

4.6.1 別名を付ける (OLD, NEW)

行レベルトリガー(FOR EACH ROW)の場合、INSERTUPDATEDELETEの対象となる行の変更前変更後の値を参照できます。参照にはDBMS固有のキーワード(例: Oracleでは:OLD, :NEW、PostgreSQLではOLD, NEW、MySQLではOLD. NEW.)を使用します。

-- Productsテーブルの価格が更新された際に、変更履歴を記録するトリガー (PostgreSQL/Oracle風) CREATE TRIGGER trg_product_price_history AFTER UPDATE OF price ON Products FOR EACH ROW BEGIN INSERT INTO ProductPriceHistory (product_id, old_price, new_price, change_date) VALUES (OLD.product_id, OLD.price, NEW.price, CURRENT_DATE); END;

4.6.2 特定の列だけを対象にする

UPDATEトリガーの場合、OF カラム名句を使用することで、特定のカラムが更新された場合にのみトリガーを起動させることができます。これにより、不要なトリガーの実行を防ぎ、パフォーマンスを向上させます。

-- Productsテーブルのpriceカラムが更新された時だけトリガーを起動 CREATE TRIGGER trg_product_price_check BEFORE UPDATE OF price ON Products -- priceカラムが更新された時のみ FOR EACH ROW BEGIN IF NEW.price < 0 THEN RAISE EXCEPTION '価格は0以上である必要があります。'; END IF; END;

4.6.3 条件を指定する (WHEN句)

WHEN句を使用すると、トリガーが起動する直前に追加の条件を指定できます。WHEN句の条件が真と評価された場合にのみ、トリガー本体の処理が実行されます。

-- Productsテーブルの在庫数が減少した場合のみ、監査ログを記録 CREATE TRIGGER trg_stock_decrease_audit AFTER UPDATE OF stock_quantity ON Products FOR EACH ROW WHEN (NEW.stock_quantity < OLD.stock_quantity) -- 在庫が減った場合のみ起動 BEGIN INSERT INTO StockAuditLog (product_id, old_quantity, new_quantity, audit_date) VALUES (OLD.product_id, OLD.stock_quantity, NEW.stock_quantity, CURRENT_DATE); END;

4.6.4 トリガーの永久ループ

トリガーの設計で最も注意すべき点の一つに**永久ループ(Infinite Loop)**があります。あるトリガーが実行され、その中で別のテーブルを更新し、そのテーブルの更新がさらに別のトリガーを起動し、それが最初のトリガーを再度起動する、というように、トリガーが連鎖的に無限に実行されてしまう状態です。

永久ループの例

  1. TableAUPDATETriggerAが起動。
  2. TriggerATableBUPDATEする。
  3. TableBUPDATETriggerBが起動。
  4. TriggerBTableAUPDATEする。
  5. 1に戻り、永久ループ。

対策

午後試験対策のポイント

午後試験では、データの整合性を保証するビジネスルールをトリガーで実装する問題や、既存のシステムで発生している性能問題の原因としてトリガーの不適切な設計(永久ループや無駄な処理)を指摘し、改善策を提案する問題が出題されることがあります。特にOLD/NEWの活用方法やWHEN句による効率化は重要です。


4.7 レプリケーション

レプリケーション(Replication: 複製)とは、データベースのデータを、ネットワークで接続された複数のデータベースサーバ(マスタスレーブ)間で複製し、常に同じ状態に保つための技術です。

マスタとスレーブ

レプリケーションの目的

  1. 高可用性 (High Availability): マスタに障害が発生した場合でも、スレーブを新しいマスタに昇格させることで、サービスを継続できます。
  2. 負荷分散 (Load Balancing): データの書き込みはマスタで行い、読み取りリクエストは複数のスレーブに分散させることで、データベース全体の負荷を軽減し、パフォーマンスを向上させます。
  3. 災害復旧 (Disaster Recovery): 遠隔地にスレーブを配置することで、マスタのあるデータセンターが災害で壊滅しても、データを保護し復旧できます。
  4. データウェアハウスへのデータ供給: マスタで発生したトランザクションデータをスレーブ経由でデータウェアハウスに転送し、分析に利用できます。

4.7.1 レプリケーションの特徴

メリット

デメリット

4.7.2 イベント型とバッチ型

レプリケーションにおけるデータ変更の伝播方式には、大きく分けてイベント型バッチ型があります。

  1. イベント型レプリケーション:

  2. バッチ型レプリケーション:

4.7.3 同期型と非同期型

レプリケーションにおけるコミットの保証度合いによって、同期型非同期型があります。

  1. 同期型レプリケーション (Synchronous Replication)

  2. 非同期型レプリケーション (Asynchronous Replication)

午後試験対策のポイント

レプリケーションは、システムの高可用性やスケーラビリティを実現するための重要な技術であり、午後試験でもシステムの要件に応じて最適なレプリケーション構成(イベント型/バッチ型、同期型/非同期型)を選択し、その理由やメリット・デメリットを説明する問題が出題されます。特に、CAP定理との関連性や、同期型と非同期型のトレードオフ(整合性と性能)は頻出テーマです。


4.8 問題対策

第4章で学んだ内容は、データベーススペシャリスト試験の午後試験、特に午後Ⅰ問題で頻繁に問われるテーマです。物理設計は、概念設計・論理設計で定義されたデータモデルを、実際のDBMS上でどのように効率的に実装・運用するかを決定する重要なフェーズだからです。

ここでは、午後試験でこれらの知識がどのように問われ、どのように解答すべきか、その対策のポイントをまとめます。

1. 索引の設計と利用条件

2. ストレージ構造とパフォーマンス

3. 区分化(パーティショニング)

4. 高度なSQL(CTE, ウィンドウ関数)

5. トリガーとレプリケーション

午後試験は、単なる知識の有無だけでなく、その知識を現実のシステム課題に適用し、最適な解決策を提案する能力が問われます。各概念を深く理解し、具体的なシナリオに基づいて考え、記述する練習を重ねることが最も効果的な対策となります。


第4章 午後試験対策 物理設計 問題集 (20問)


問題 1 (複合索引 - 前方一致の原則)

Ordersテーブルに(customer_id, order_date, total_amount)という複合索引が作成されている。以下のWHERE句を持つSQL文のうち、この複合索引が有効に利用されるものはどれか。複数選択可。

ア. WHERE customer_id = 101
イ. WHERE order_date = '2025-01-01'
ウ. WHERE customer_id = 101 AND order_date > '2025-01-01'
エ. WHERE order_date = '2025-01-01' AND total_amount > 1000
オ. WHERE customer_id = 101 AND order_date = '2025-01-01' AND total_amount > 1000

解答と解説

解答: ア, ウ, オ

解説:
複合索引は「前方一致の原則」に従い、先頭から連続した部分に対して利用されます。


問題 2 (索引が使用されない条件)

Productsテーブルのproduct_nameカラムに索引が作成されている。以下のSQL文のうち、この索引が利用されない可能性が高いものはどれか。

ア. SELECT * FROM Products WHERE product_name LIKE 'デスク%';
イ. SELECT * FROM Products WHERE SUBSTR(product_name, 1, 1) = 'デ';
ウ. SELECT * FROM Products WHERE product_name IS NOT NULL;
エ. SELECT * FROM Products WHERE product_name = 'ノートPC';

解答と解説

解答: イ

解説:
WHERE句で索引カラムに対して関数を適用すると、オプティマイザは索引を利用せずフルテーブルスキャンを選択する可能性が高いです。


問題 3 (クラスタ率)

データベースのクラスタ率(Clustering Factor)とは何か。また、それが低い場合にどのような問題が発生するか簡潔に説明しなさい。

解答と解説

解答:
クラスタ率とは、テーブルの物理的な格納順序が、特定の索引の論理的な順序とどの程度一致しているかを示す指標です。

問題点: クラスタ率が低い場合、索引を使った範囲検索(Index Range Scan)の際に、データがディスク上のあちこちに散らばって格納されているため、多くのディスクI/Oが発生し、クエリのパフォーマンスが大幅に低下します。


問題 4 (表領域の役割)

データベースの表領域(Tablespace)の主な役割を2つ挙げなさい。

解答と解説

解答例:

  1. ストレージ管理: 異なる種類のデータ(ユーザーデータ、索引、ログなど)を論理的に分離し、物理的なディスクに割り当てることで、効率的なI/O管理やディスク領域の割り当て制御が可能になる。
  2. バックアップとリカバリ: 表領域単位でのバックアップやリカバリが可能になり、データベース管理の柔軟性と効率が向上する。
  3. パフォーマンスの最適化: 異なるI/O特性を持つディスクデバイスに、性能要件の異なるデータを格納する表領域を配置することで、全体のパフォーマンスを最適化できる。

問題 5 (PCTFREE)

PCTFREEパラメータの主な目的は何か。簡潔に説明しなさい。

解答と解説

解答:
PCTFREEは、データベースのページ(ブロック)内に、将来のデータ更新によって行のサイズが拡張された際に、その行が同じページ内に収まるように確保しておく空き領域の割合を指定するパラメータです。これにより、行のマイグレーション(行移動)やチェイニング(行連鎖)を防ぎ、I/O性能の低下を抑制することを目的とします。


問題 6 (パーティショニングのメリット)

テーブルのパーティショニング(区分化)を導入するメリットとして、最も適切なものはどれか。

ア. データの冗長性を完全に排除できる。
イ. クエリのWHERE句の条件に関わらず、必ず検索性能が向上する。
ウ. 特定のパーティションだけを対象にバックアップやアーカイブが可能になり、管理性が向上する。
エ. INSERTUPDATEDELETEの処理が常に高速になる。

解答と解説

解答: ウ

解説:
パーティショニングのメリットの一つに、特定期間のデータや特定カテゴリのデータなど、パーティション単位で独立した管理が可能になることが挙げられます。これにより、バックアップ、アーカイブ、メンテナンスなどの管理作業の柔軟性が増します。


問題 7 (パーティショニングの種類)

データを日付の範囲(例: 年、月)に基づいて分割するパーティショニングの種類は何か。

ア. レンジ区分化 (Range Partitioning)
イ. リスト区分化 (List Partitioning)
ウ. ハッシュ区分化 (Hash Partitioning)
エ. コンポジット区分化 (Composite Partitioning)

解答と解説

解答: ア

解説:
レンジ区分化は、特定のカラムの値の範囲に基づいてデータを分割する方法で、時系列データや連続的な数値データに適しています。


問題 8 (共通テーブル式 - CTE)

共通テーブル式(CTE)を使用する主なメリットを1つ挙げなさい。

解答と解説

解答例:

  1. 可読性の向上: 複雑なクエリを複数の論理的なステップに分割できるため、SQL文が読みやすく理解しやすくなる。
  2. 再利用性: 同じ一時的な結果セットをクエリ内で複数回参照できるため、コードの重複を減らせる。
  3. 再帰クエリの実現: 階層構造のデータ(例: 組織図、部品構成表)を処理する再帰クエリを記述できる。

問題 9 (ウィンドウ関数)

Productsテーブルにおいて、各製品のcategory_idごとに、その製品の価格がカテゴリ内の平均価格より高いかどうかを判定するSELECT文を完成させなさい。

SELECT product_name, category_id, price, CASE WHEN price > AVG(price) OVER (PARTITION BY category_id) THEN '高い' ELSE '高くない' END AS price_comparison FROM Products;

このSELECT文のOVER句の中の[ ______ ]に当てはまるものは何か。

解答と解説

解答: PARTITION BY category_id

解説:
PARTITION BY句は、ウィンドウ関数を適用する行のグループ(区分)を定義します。この場合、category_idごとに平均価格を計算するため、PARTITION BY category_idと指定します。


問題 10 (LAG関数)

Productsテーブルのデータを使って、release_dateでソートした際に、各製品の「前の製品の価格」を取得するSQL文を完成させなさい。(前の製品がない場合は0とする)

SELECT product_name, release_date, price, LAG(price, 1, 0) OVER (ORDER BY release_date) AS previous_product_price FROM Products;

このSELECT文のOVER句の中の[ ______ ]に当てはまるものは何か。

解答と解説

解答: ORDER BY release_date

解説:
LAG()関数は、ウィンドウ内で指定された順序に基づいて、現在の行の前の行の値を返します。LAG(price, 1, 0)は、1つ前の行のpriceを取得し、もし前の行がなければ0を返します。この「前の行」を決定するためには、ウィンドウ内の順序をORDER BY句で指定する必要があります。


問題 11 (順位関数)

category_id内でpriceが高い順に製品の順位を付与したい。同じ価格の製品には同じ順位を付け、次の順位は重複した数だけスキップされる順位付けを行うウィンドウ関数は何か。

ア. ROW_NUMBER()
イ. RANK()
ウ. DENSE_RANK()
エ. NTILE()

解答と解説

解答: イ

解説:


問題 12 (トリガーの起動タイミング)

AFTER UPDATE ON Orders FOR EACH ROWというトリガーは、どのようなタイミングで起動するか。

ア. Ordersテーブルの行が更新される直前。
イ. Ordersテーブルの行が更新された直後。
ウ. Ordersテーブルに対してUPDATE文が実行される直前。
エ. Ordersテーブルに対してUPDATE文が実行された直後。

解答と解説

解答: イ

解説:
AFTERは、イベント(UPDATE)が発生した後に起動します。FOR EACH ROWは、更新された各行に対してトリガーが起動することを意味します。したがって、Ordersテーブルの行が更新された直後に起動します。


問題 13 (トリガーのOLD/NEW)

Productsテーブルのpriceカラムが更新された際に、トリガー内で更新前の価格と更新後の価格を比較したい。それぞれOLD.priceNEW.priceという形式でアクセスできるが、これはどの種類のトリガーで可能か。

ア. BEFORE STATEMENTトリガー
イ. AFTER STATEMENTトリガー
ウ. BEFORE ROWトリガー
エ. AFTER INSERTトリガー

解答と解説

解答: ウ

解説:
OLDおよびNEWの参照は、行レベルトリガー(FOR EACH ROW句が指定されたトリガー)でのみ可能です。BEFOREトリガーではNEWの値を変更できますが、AFTERトリガーではできません。UPDATEトリガーで両方の値を比較できるのはBEFOREまたはAFTERの行レベルトリガーです。選択肢にはBEFORE ROWトリガーがあります。


問題 14 (トリガーの永久ループ)

データベースにおけるトリガーの「永久ループ」とは何か。簡潔に説明しなさい。

解答と解説

解答:
トリガーの永久ループとは、あるトリガーが実行された結果、そのトリガー自身を再度起動したり、別のトリガーを起動し、その別のトリガーが最初のトリガーを起動する、というように、トリガーが連鎖的に無限に実行されてしまう状態のことです。システムのリソースを枯渇させ、データベースを停止させる可能性があります。


問題 15 (レプリケーションの目的)

データベースのレプリケーションを導入する主な目的を2つ挙げなさい。

解答と解説

解答例:

  1. 高可用性 (High Availability): マスタサーバに障害が発生した場合でも、スレーブサーバを新しいマスタに昇格させることで、サービスの中断時間を最小限に抑える。
  2. 負荷分散 (Load Balancing): データの書き込みはマスタで行い、読み取りリクエストはスレーブに分散させることで、データベース全体の処理能力を向上させる。
  3. 災害復旧 (Disaster Recovery): 遠隔地にスレーブを配置することで、地理的な災害が発生した場合でもデータを保護し、復旧を可能にする。
  4. データウェアハウスへのデータ供給: マスタの運用に影響を与えず、スレーブからデータ分析用のデータを提供できる。

問題 16 (レプリケーション - 同期型と非同期型)

同期型レプリケーションと非同期型レプリケーションにおける、データの整合性とパフォーマンスに関するトレードオフについて簡潔に説明しなさい。

解答と解説

解答:


問題 17 (物理設計 - ページとブロック)

データベースの「ページ」または「ブロック」とは何か。簡潔に説明しなさい。

解答と解説

解答:
ページ(またはブロック)は、データベースにおいてディスクI/Oの最小単位となる記憶領域のことです。データベースがディスクからデータを読み書きする際には、必ずこのページ単位で行われます。テーブルの行データや索引のエントリなどがページ内に格納されます。


問題 18 (索引が使用されない条件 - 型変換)

product_idINT型で索引が作成されているProductsテーブルに対し、SELECT * FROM Products WHERE product_id = '123';というSQL文が実行された場合、索引が利用されない可能性がある。その主な理由を簡潔に説明しなさい。

解答と解説

解答:
product_idカラムがINT型であるにもかかわらず、WHERE句で文字列リテラル'123'と比較しているため、DBMSがproduct_idカラムに対して暗黙的な型変換を行ってしまう可能性があります。カラム自体に型変換の関数が適用されたのと同じ状態になり、索引の利用効率が著しく低下するか、全く利用されなくなるためです。


問題 19 (ウィンドウ関数 - NTILE)

NTILE(n)ウィンドウ関数は、どのような計算を行うために使用されるか。簡潔に説明しなさい。

解答と解説

解答:
NTILE(n)ウィンドウ関数は、ウィンドウ内の行を、指定されたn個のグループに均等に分割し、各行がどのグループ(階級)に属するかを示す番号を返します。例えばNTILE(4)は、データを4つの四分位に分割するために使用できます。


問題 20 (午後対策 - EXPLAIN)

午後試験で、遅いSQLの性能改善のためにEXPLAINコマンドの実行結果を分析する問題が出題された場合、特にどのような情報に注目すべきか、2つ挙げなさい。

解答と解説

解答例:

  1. フルテーブルスキャン (Full Table Scan) の有無: 意図しないフルテーブルスキャンが発生している場合、索引が適切に利用されていない可能性が高い。
  2. 索引の利用状況: どの索引が利用されているか、あるいは利用されていないかを確認する。利用されている場合でも、Index Range ScanかIndex Full Scanかなど、利用効率の度合いを見る。
  3. ソート処理の有無: ORDER BY句やGROUP BY句でソート処理が発生している場合、これを索引によって回避できないか検討する。
  4. JOINの種類: JOINの種類(ネステッドループ、ハッシュ、マージなど)や結合順序が適切かを確認する。
  5. I/Oコスト、CPUコスト: 各操作にかかるコストがどこに集中しているかを確認する。

第5章 午後試験対策 論理設計

この章では、データベーススペシャリスト試験の午後問題、特に午後Ⅱ問題で頻繁に出題される論理設計に焦点を当てます。概念設計で作成したE-R図をリレーショナルデータベースのテーブル構造に正確に落とし込み、データの冗長性を排除し、整合性を保つための知識が問われます。

5.1 概念データモデル

概念設計で作成する概念データモデルは、ビジネス要件をデータベースの構造に変換する最初のステップです。ここでは、E-R図の要素をより深く理解し、午後試験で与えられる業務記述から正確なデータモデルを導き出すためのポイントを解説します。

5.1.1 E-R図

E-R図は、概念データモデルを視覚的に表現するツールであり、午後試験では問題文の業務記述をE-R図で表現する能力や、与えられたE-R図を解釈する能力が問われます。

E-R図の要素の再確認と午後対策のポイント

E-R図の例 (再掲)

erDiagram CUSTOMER ||--o{ ORDER : "places" ORDER ||--o{ ORDER_DETAIL : "includes" PRODUCT ||--o{ ORDER_DETAIL : "is_part_of" CUSTOMER { int customer_id PK string customer_name string address string phone_number } ORDER { int order_id PK int customer_id FK date order_date string status } PRODUCT { int product_id PK string product_name decimal price int stock_quantity } ORDER_DETAIL { int order_id PK, FK int product_id PK, FK int quantity decimal unit_price }

午後試験では、このようなE-R図を業務記述から作成したり、E-R図の不備を指摘する問題が出題されます。

5.1.2 リレーションシップ

リレーションシップはエンティティ間のつながりを示し、その「強さ」や「数」を表す**多重度(カーディナリティ)参加の任意性(オプショナリティ)**を正確に読み取ることが重要です。

多重度(Cardinality)

参加の任意性(Optionality)

リレーションシップの線とエンティティの接続部分に表示される記号で、そのエンティティがリレーションシップに必ず参加しなければならないか(必須:Mandatory)、**参加しなくてもよいか(任意:Optional)**を示します。

erDiagram CUSTOMER ||--o{ ORDER : "places" EMPLOYEE ||--|{ DEPARTMENT : "belongs_to"

午後試験では、業務要件を正確に読み解き、適切な多重度と任意性をE-R図に反映できるかが評価のポイントとなります。

5.1.3 リレーションシップと参照制約

概念設計におけるリレーションシップは、論理設計で外部キー(FOREIGN KEY)による参照制約として実装されます。参照制約は、関連するテーブル間のデータの整合性を保証する重要な機能です。

参照制約 (Referential Constraint)

参照制約アクション (ON DELETE / ON UPDATE)

親テーブルの行が削除(ON DELETE)または更新(ON UPDATE)された際に、関連する子テーブルの行に対してどのような操作を行うかを定義します。午後試験では、業務ルールに基づいてこれらのアクションを適切に選択する能力が問われます。

  1. NO ACTION / RESTRICT:
  2. CASCADE:
  3. SET NULL:
  4. SET DEFAULT:
-- Productsテーブル (子) が Categoriesテーブル (親) を参照する例 CREATE TABLE Products ( product_id INT PRIMARY KEY, category_id INT, ... FOREIGN KEY (category_id) REFERENCES Categories(category_id) -- 参照制約 ON DELETE SET NULL -- 親カテゴリが削除されたら、製品のcategory_idはNULLになる ON UPDATE CASCADE -- 親カテゴリのcategory_idが更新されたら、製品のcategory_idも自動更新される );

5.1.4 間違いやすいリレーションシップ

午後試験では、一見簡単そうに見える業務記述の中に、リレーションシップの落とし穴が隠されていることがあります。特に注意すべきパターンを理解しておきましょう。

  1. 多対多のリレーションシップの見落とし:

  2. 自己参照(再帰的)リレーションシップの見落とし:

  3. 排他的リレーションシップ:

  4. 属性とエンティティの混同:

これらのパターンを理解し、業務記述から正確にモデル化する訓練が午後試験突破の鍵となります。

5.1.5 スーパタイプとサブタイプ

**スーパタイプ(Supertype: 上位型)サブタイプ(Subtype: 下位型)**は、オブジェクト指向の「継承」の概念をデータモデルに適用したもので、「is-a」の関係(~である)を表現します。共通の特性を持つエンティティ群を一般化(汎化)してスーパタイプとし、固有の特性を持つサブタイプを特殊化(特化)して表現します。

スーパタイプ/サブタイプの例

erDiagram EMPLOYEE ||--o{ FULL_TIME_EMPLOYEE : "is a" EMPLOYEE ||--o{ PART_TIME_EMPLOYEE : "is a" EMPLOYEE ||--o{ CONTRACT_EMPLOYEE : "is a" EMPLOYEE { int employee_id PK string employee_name date birth_date } FULL_TIME_EMPLOYEE { int employee_id PK, FK decimal monthly_salary } PART_TIME_EMPLOYEE { int employee_id PK, FK decimal hourly_wage int work_hours } CONTRACT_EMPLOYEE { int employee_id PK, FK date contract_end_date }

包含制約 (Disjoint/Overlap)

完全性制約 (Completeness)

午後試験対策のポイント

午後試験では、複雑な業務ルール(例: 従業員の種類による属性の違い)をスーパタイプ/サブタイプで適切にモデリングする能力や、その実装方法(リレーショナルスキーマへの変換)が問われます。特に包含制約と完全性制約を業務記述から正確に判断することが重要です。


5.2 関係スキーマとテーブル構造

概念設計で作成したE-R図を、リレーショナルデータベースで実際に構築するためのテーブル構造(関係スキーマ)に変換する詳細なステップが論理設計の後半部分です。ここでは、各要素がどのようにテーブルとして表現されるかを具体的に見ていきます。

5.2.1 主キー

**主キー(Primary Key)**は、リレーショナルテーブルの各行を一意に識別するためのカラム(またはカラムの組み合わせ)です。

主キーの選定と午後試験対策

午後試験では、業務要件から主キーを適切に選定できるかが問われます。

  1. 一意性: どの行も重複する値を持たないこと。
  2. 非NULL性: 値がNULLであってはならないこと。
  3. 不変性: 原則として、値が変更されないこと。
  4. 簡潔性: 可能な限り短い、少ないカラム数で構成されること。

午後試験では、自然キーと代理キーのどちらを選ぶべきか、それぞれのメリット・デメリットを考慮して判断する問題が出題されます。特に、複合主キー(複数のカラムを組み合わせた主キー)の設計では、部分関数従属を発生させないよう注意が必要です。

5.2.2 外部キー

**外部キー(Foreign Key)**は、テーブル間のリレーションシップを表現するためのカラムです。子テーブルの外部キーが、親テーブルの主キーを参照することで、関連性のあるデータの一貫性(参照整合性)を保ちます。

外部キーの定義と午後試験対策

5.2.3 その他の属性

主キーや外部キー以外のカラムは、エンティティが持つ具体的な情報、つまり「非キー属性」となります。これらの属性に対しても、データ型、NOT NULL制約、UNIQUE制約、CHECK制約などを適切に設定し、データ整合性を確保する必要があります。

派生属性(Derived Attributes)

他の属性から計算で導き出せる属性を派生属性と呼びます(例: 生年月日から年齢を計算)。

午後試験では、派生属性をデータベースに格納すべきか、クエリ実行時に計算すべきか、性能要件や更新頻度などを考慮して判断する問題が出題されることがあります。

5.2.4 スーパタイプとサブタイプ

概念設計で定義したスーパタイプとサブタイプを、リレーショナルデータベースのテーブル構造に落とし込む方法にはいくつかのパターンがあります。午後試験では、それぞれの実装方法のメリット・デメリットを理解し、業務要件に合った最適な方法を選択する能力が問われます。

  1. 単一テーブル方式 (Single Table Inheritance)

  2. クラス階層テーブル方式 (Class Table Inheritance / 継承テーブル方式)

  3. 具象テーブル方式 (Concrete Table Inheritance)

午後試験での選択のポイント

午後試験では、これらの実装方法について、業務要件(例: 検索頻度、更新頻度、サブタイプの追加・削除頻度)や性能要件、保守性などを考慮し、最適なものを選択し、その理由を論理的に説明できる能力が問われます。


5.3 問題対策

第5章で学んだ論理設計の知識は、データベーススペシャリスト試験の午後Ⅱ問題の核となる部分です。午後Ⅱでは、多くの場合、与えられた業務記述を基にE-R図を作成・修正したり、正規化を進めて関係スキーマを定義したりする能力が問われます。

ここでは、午後試験でこれらの知識がどのように問われ、どのように解答すべきか、その対策のポイントをまとめます。

1. 業務記述からの概念データモデル作成

2. 論理設計と正規化

3. スーパタイプ/サブタイプのモデリング

午後Ⅱ問題は、与えられた情報から論理的な思考を重ね、設計プロセスを追体験するような問題が多いです。単なる知識の暗記だけでなく、なぜそのような設計になるのか、どのようなメリット・デメリットがあるのかを自分の言葉で論理的に説明できる能力が問われます。多くの過去問を実際に解き、模範解答と自分の解答を比較分析する訓練を徹底しましょう。


第5章 午後試験対策 論理設計 問題集 (20問)


問題 1 (概念設計の成果物)

概念データモデルの主要な成果物であり、エンティティ、属性、リレーションシップを視覚的に表現する図は何か。

ア. データフロー図 (DFD)
イ. 状態遷移図 (STD)
ウ. クラス図
エ. E-R図 (エンティティ関連図)

解答と解説

解答: エ

解説:
E-R図は、データベースの概念設計において、現実世界に存在するモノやコト、それらの属性、そしてモノやコト同士の関係を視覚的に表現するための図法です。


問題 2 (リレーションシップの多重度)

「1つの製品は複数の部品で構成され、1つの部品は複数の製品に使用される」という関係の多重度(カーディナリティ)は何か。

ア. 1対1
イ. 1対多
ウ. 多対多
エ. 多対1

解答と解説

解答: ウ

解説:
一方のエンティティの1つのインスタンスが他方の複数のインスタンスと関連し、かつ他方の1つのインスタンスも最初の複数のインスタンスと関連する場合、多対多(N:M)の関係となります。


問題 3 (参加の任意性)

E-R図で「参加が任意」であることを示す表記(例: クローズフィート記法)はどれか。

ア. 線上に1本の縦棒
イ. 線上に2本の縦棒
ウ. 線上に小さな円
エ. 線上にクロウズフィート(カラスの足)

解答と解説

解答: ウ

解説:
クローズフィート記法では、参加が必須の場合は線上に縦棒(|)を、任意の場合は小さな円(o)を記します。


問題 4 (参照制約アクション - ON DELETE)

親テーブルの行が削除された際に、関連する子テーブルの行も自動的に削除されるようにするON DELETEアクションはどれか。

ア. NO ACTION
イ. RESTRICT
ウ. SET NULL
エ. CASCADE

解答と解説

解答: エ

解説:
ON DELETE CASCADEは、親テーブルの行が削除されると、その親を参照している子テーブルの関連する行も自動的に削除する動作です。


問題 5 (多対多解消)

E-R図で多対多のリレーションシップを表現した場合、論理設計でリレーショナルスキーマに変換する際には、どのように解消するのが一般的か。簡潔に説明しなさい。

解答と解説

解答:
多対多のリレーションシップは、直接リレーショナルスキーマ(テーブル)で表現できないため、間に**関連エンティティ(連関エンティティ)**を導入して解消します。この関連エンティティは、元の2つのエンティティの主キーを外部キーとして持ち、それらを複合主キーとすることが一般的です。


問題 6 (自己参照リレーションシップ)

「従業員が上司を持つ(上司も従業員である)」という階層構造をデータベースで表現するためのリレーションシップの種類は何か。

ア. 排他的リレーションシップ
イ. 多対多リレーションシップ
ウ. 自己参照リレーションシップ
エ. 外部キーリレーションシップ

解答と解説

解答: ウ

解説:
自己参照リレーションシップは、エンティティ自身が自分自身とリレーションシップを持つ場合で、階層構造を表現する際によく用いられます。この場合、EMPLOYEEテーブル内に上司IDカラムを設け、それがEMPLOYEE.employee_idを参照する外部キーとなります。


問題 7 (スーパタイプ/サブタイプ - 完全性制約)

スーパタイプ/サブタイプのリレーションシップにおいて、スーパタイプの全てのインスタンスが必ずいずれかのサブタイプに属さなければならないという制約を何と呼ぶか。

ア. 排他制約
イ. 重なり制約
ウ. 完全性制約 (Complete)
エ. 部分性制約 (Partial)

解答と解説

解答: ウ

解説:
完全性制約(Complete Constraint)は、スーパタイプのインスタンスが、必ず一つ以上のサブタイプに属することを要求します。


問題 8 (スーパタイプ/サブタイプ - 包含制約)

スーパタイプのインスタンスが、いずれか一つのサブタイプにのみ属することができるという包含制約を何と呼ぶか。

ア. 排他 (Disjoint)
イ. 重なり (Overlap)
ウ. 完全 (Complete)
エ. 部分 (Partial)

解答と解説

解答: ア

解説:
排他(Disjoint)制約は、スーパタイプのインスタンスが、複数のサブタイプに同時に属することを禁止します。重なり(Overlap)はその逆で、複数のサブタイプに属することを許容します。


問題 9 (主キーの要件)

主キーが満たすべき要件として、適切でないものはどれか。

ア. 一意性(各行を一意に識別できること)
イ. 非NULL性(値がNULLであってはならないこと)
ウ. 不変性(原則として、値が変更されないこと)
エ. 業務上の意味を必ず持つこと(自然キーであること)

解答と解説

解答: エ

解説:
主キーは業務上の意味を持つ自然キーでも、システムが自動生成する意味を持たない代理キー(サロゲートキー)でも構いません。実際、代理キーの方が不変性や簡潔性に優れるため、広く利用されます。


問題 10 (代理キーの利点)

主キーとして代理キー(サロゲートキー)を使用する主な利点を1つ挙げなさい。

解答と解説

解答例:

  1. 不変性: 業務上の意味を持たないため、業務ルールの変更やデータの意味合いの変更があっても、主キーの値自体が変更されるリスクが低い。
  2. 簡潔性: 通常、連番などの短い形式であり、複合キーのように複数のカラムで構成されないため、主キーや外部キーとして参照する際の記述がシンプルになる。
  3. 一意性の保証: システムが自動的に生成するため、重複する値が発生しないことが保証されやすい。

問題 11 (派生属性)

顧客テーブルに生年月日カラムがあり、年齢カラムは生年月日から計算できる派生属性である。この年齢カラムをデータベースに格納しない設計を選択した場合の主なメリットは何か。

解答と解説

解答:
常に最新の年齢が取得できること(データの整合性が保たれること)と、年齢カラム分のストレージ容量を節約できることです。格納しない場合、生年月日が更新されれば年齢も自動的に最新になるため、更新時のデータ不整合リスクがありません。


問題 12 (スーパタイプ/サブタイプ - 単一テーブル方式)

スーパタイプ/サブタイプの実装方法の一つである「単一テーブル方式」の主なデメリットを1つ挙げなさい。

解答と解説

解答例:

  1. NULL値の多発: 各サブタイプ固有の属性をすべて一つのテーブルに持つため、あるサブタイプのレコードでは他のサブタイプの属性がNULLとなり、NULL値が多く発生しストレージ効率が低下する。
  2. テーブルの肥大化と管理の複雑化: サブタイプや属性が増えるとテーブルのカラム数が非常に多くなり、管理やクエリが複雑になる。
  3. 整合性制約の困難さ: サブタイプ固有の制約(例: 正社員月給0より大きい)を実装するのが難しい、またはCHECK制約が複雑になる。

問題 13 (スーパタイプ/サブタイプ - クラス階層テーブル方式)

スーパタイプ/サブタイプの実装方法の一つである「クラス階層テーブル方式」が「単一テーブル方式」と比較して優れている点(メリット)を1つ挙げなさい。

解答と解説

解答例:

  1. NULL値の削減: 各サブタイプ固有の属性がそれぞれのテーブルに格納されるため、NULL値の発生が抑えられ、ストレージ効率が向上する。
  2. サブタイプ固有の制約定義の容易さ: 各サブタイプテーブルで固有の制約(NOT NULLなど)を明確に定義できる。
  3. 柔軟性: 新しいサブタイプを追加する際に、既存のテーブル構造に大きな変更を加える必要がない。

問題 14 (E-R図の多対多解消後の関係スキーマ)

学生エンティティと科目エンティティの間に「多対多」の履修リレーションシップがある。これを論理設計で解消し、関係スキーマとして表現しなさい。

解答と解説

解答:
以下のように3つのテーブルに分解する。

ここで、履修テーブルが関連エンティティとなり、学生ID科目IDの複合主キーを持つ。


問題 15 (論理設計 - 非キー属性)

主キーでも外部キーでもない、エンティティが持つ具体的な情報を示すカラムを何と呼ぶか。

ア. 候補キー
イ. 非キー属性
ウ. 複合属性
エ. 派生属性

解答と解説

解答: イ

解説:
非キー属性(Non-Key Attribute)は、主キーでも外部キーでもない、エンティティの具体的な特徴を表す属性です。


問題 16 (排他的リレーションシップの例)

取引先顧客であるか、または仕入先であるかのいずれかであり、両方ではない」という業務ルールは、どのような種類のリレーションシップを示すか。

解答と解説

解答:
排他的リレーションシップです。取引先というスーパタイプに対して、顧客仕入先というサブタイプが排他(Disjoint)の関係にあることを示します。


問題 17 (派生属性の格納判断)

商品テーブルに原価売価があり、利益率(売価 - 原価) / 売価 * 100 で計算できる派生属性である。この利益率をテーブルに格納する設計を選択した場合の主なデメリットは何か。

解答と解説

解答:
データの更新時にデータ不整合が発生するリスクがあることです。原価売価が更新された際に利益率も同時に更新しないと、利益率の値が古くなり、実際の値と乖離してしまう可能性があります。また、利益率分のストレージ容量も余計に消費します。


問題 18 (参照制約アクション - SET NULLの制約)

ON DELETE SET NULLアクションを持つ参照制約を設定する際、子テーブルの外部キーカラムに対してどのような制約がないことを確認する必要があるか。

解答と解説

解答:
子テーブルの外部キーカラムが**NOT NULL制約**を持っていないことを確認する必要があります。SET NULLアクションは、親の行が削除された際に子の外部キーをNULLにするため、子の外部キーがNOT NULL制約を持っているとエラーが発生します。


問題 19 (論理設計での正規化の重要性)

データベースの論理設計において、正規化を行うことが特に重要な理由を簡潔に説明しなさい。

解答と解説

解答:
論理設計段階での正規化は、データの冗長性を排除し、更新、挿入、削除の際に発生しうるデータ異常(アノマリ)を防止することで、データベース全体のデータ整合性(一貫性)を確保するために不可欠です。これにより、データの品質と信頼性が向上し、アプリケーション開発や保守の容易性にも寄与します。


問題 20 (午後Ⅱ問題の対策 - E-R図)

午後Ⅱ問題において、与えられた業務記述からE-R図を作成する際、特にどのような点に注意して記述を読み解くべきか、2つ挙げなさい。

解答と解説

解答例:

  1. 名詞と動詞の区別: 業務記述中の名詞はエンティティや属性の候補、動詞はリレーションシップの候補となるため、これらを正確に識別する。
  2. 多重度と任意性の明示: 「必ず〜する」「〜の可能性がある」「複数の〜」といった表現に注目し、リレーションシップの多重度(1対1, 1対多, 多対多)と参加の任意性(必須/任意)を正確に判断する。
  3. 主キー候補の特定: 各エンティティを一意に識別できる属性(または属性の組み合わせ)を見つける。
  4. 関連エンティティの必要性: 多対多のリレーションシップが存在しないかを確認し、必要であれば関連エンティティを導入する。

第6章 業務知識

データベーススペシャリスト試験の午後問題、特に午後Ⅱでは、単なるデータベースの技術知識だけでなく、与えられた業務を深く理解し、それをデータモデルとして表現する能力が問われます。そのためには、ITシステムが支える主要な業務プロセス(業務知識)を把握しておくことが不可欠です。

この章では、代表的な業務プロセスである「販売管理」と「生産管理」に焦点を当て、その流れ、登場する主要なデータ(エンティティ)、そしてデータ間の関係性を分かりやすく解説します。

6.1 販売管理

販売管理とは、顧客への「見積」から「受注」、「出荷」、「請求」、「入金」までの一連の業務プロセスを管理することです。企業の売上に関わる根幹の業務であり、データベースで管理される情報の典型例です。

6.1.1 見積

見積は、顧客からの引き合い(問い合わせ)に対し、商品やサービスの価格、数量、納期などを提示する業務です。

graph TD A["顧客からの問い合わせ"] --> B["見積作成"]; B --> C["顧客へ提示"]; C -- "承認" --> D["見積承認"]; C -- "却下" --> E["見積却下"];
erDiagram CUSTOMER ||--o{ QUOTATION : "requests" QUOTATION ||--o{ QUOTATION_DETAIL : "contains" PRODUCT ||--o{ QUOTATION_DETAIL : "includes"

6.1.2 受注

受注は、顧客から提示された見積や、それ以外の方法で、正式な注文(オーダー)を受け付ける業務です。

graph TD A["顧客からの注文"] --> B["受注登録"]; B --> C["在庫・納期確認"]; C --> D["顧客へ納期回答"];
erDiagram CUSTOMER ||--o{ ORDER : "places" ORDER ||--o{ ORDER_DETAIL : "contains" PRODUCT ||--o{ ORDER_DETAIL : "includes" QUOTATION ||--o| ORDER : "generated_from"

QUOTATIONORDERは1対1または1対多の関係(1つの見積もりから複数の注文が発生することもあるため)。

6.1.3 出荷指示

出荷指示は、受注した商品を倉庫から顧客へ発送するよう、倉庫部門に指示を出す業務です。

erDiagram ORDER ||--o{ SHIPPING_INSTRUCTION : "instruct_shipping" SHIPPING_INSTRUCTION ||--o{ SHIPPING_INSTRUCTION_DETAIL : "contains" PRODUCT ||--o{ SHIPPING_INSTRUCTION_DETAIL : "includes"

6.1.4 出庫指示と出庫実績

出庫指示は、出荷指示に基づいて倉庫内で特定の商品をピッキング(取り出し)するよう作業員に指示する業務です。出庫実績は、実際に出庫された内容を記録する業務です。

erDiagram SHIPPING_INSTRUCTION ||--o{ PICKING_INSTRUCTION : "generates" PICKING_INSTRUCTION ||--o{ PICKING_INSTRUCTION_DETAIL : "contains" PRODUCT ||--o{ PICKING_INSTRUCTION_DETAIL : "instructs_to_pick" PICKING_INSTRUCTION ||--o{ PICKING_RESULT : "records_result_of" PRODUCT ||--o{ PICKING_RESULT : "picked"

6.1.5 出荷実績

出荷実績は、実際に出荷が完了した内容を記録する業務です。出庫実績と照合され、最終的な顧客への出荷情報を確定します。

erDiagram PICKING_RESULT ||--o{ SHIPPING_RECORD : "generates" SHIPPING_RECORD ||--o{ SHIPPING_RECORD_DETAIL : "contains" PRODUCT ||--o{ SHIPPING_RECORD_DETAIL : "shipped"

6.1.6 請求

請求は、出荷した商品やサービスに対して、顧客に代金の支払いを要求する業務です。

erDiagram CUSTOMER ||--o{ INVOICE : "receives" ORDER ||--o| INVOICE : "associated_with" INVOICE ||--o{ INVOICE_DETAIL : "contains" PRODUCT ||--o{ INVOICE_DETAIL : "billed"

販売管理業務フロー全体の概要

graph TD 見積("見積") --> 受注("受注"); 受注 --> 出荷指示("出荷指示"); 出荷指示 --> 出庫指示("出庫指示"); 出庫指示 --> 出庫実績("出庫実績"); 出庫実績 --> 出荷実績("出荷実績"); 出荷実績 --> 請求("請求"); 請求 --> 入金("入金");

午後試験では、このような一連の業務フロー全体を俯瞰し、各エンティティ間の連携やデータの一貫性をどのように保つべきかが問われます。


6.2 生産管理

生産管理とは、顧客の需要や販売計画に基づいて、製品を効率的に製造し、供給するまでの一連の業務プロセスを管理することです。原材料の調達から製造計画、生産実行、品質管理、完成品の在庫管理まで多岐にわたります。

6.2.1 製造を行うきっかけ

製品の製造は、様々なきっかけで開始されます。これを生産トリガーとも呼びます。

  1. 需要予測・販売計画:
  2. 顧客からの受注:
  3. 在庫補充:
  4. 他部門からの依頼:

登場する主なデータ(エンティティ):

6.2.2 品目

**品目(Item)**とは、生産管理において扱う全ての「モノ」の総称です。完成品、半製品、部品、原材料など、種類に関わらず一意に識別・管理されます。

部品構成表 (Bill Of Materials: BOM)

品目の中でも、完成品や半製品を製造するためには、どの部品がどれだけ必要かを示す**部品構成表(BOM)**が非常に重要です。部品構成表は階層構造をしており、製品とその部品、さらにその部品の部品といった関係を管理します。

graph TD A["製品A"] --> B["部品B"]; A --> C["部品C"]; B --> D["部品D"]; C --> D; C --> E["部品E"];

業務では、このような階層構造を持つデータを扱うことが多いため、午後試験でも関連問題が出題されることがあります。

6.2.3 所要量展開 (Material Requirements Planning: MRP)

所要量展開(MRP)は、生産計画や顧客からの注文(独立需要)に基づいて、完成品を製造するために必要な部品や原材料の必要量と必要時期を計算することです。部品構成表(BOM)がこの計算の基礎となります。

6.2.4 製造指図

製造指図は、所要量展開の結果に基づいて、実際に製品や部品を製造するよう製造現場に指示を出す業務です。

6.2.5 発注と入荷

生産に必要な原材料や部品の不足分は、外部の仕入先(サプライヤー)に発注し、それが届けられた際に入荷として受け入れます。

graph TD A["所要量展開"] --> B["発注"]; B --> C["入荷"];
erDiagram SUPPLIER ||--o{ PURCHASE_ORDER : "supplies for" PURCHASE_ORDER ||--o{ PURCHASE_ORDER_DETAIL : "contains" ITEM ||--o{ PURCHASE_ORDER_DETAIL : "orders" PURCHASE_ORDER ||--o{ GOODS_RECEIPT : "receives" ITEM ||--o{ GOODS_RECEIPT : "received"

生産管理業務フロー全体の概要

graph TD A["需要/計画"] --> B["所要量展開_MRP"]; B --> C{"部品不足?"}; C -- "Yes" --> D["発注"]; D --> E["入荷"]; C -- "No" --> F["製造指図"]; E --> F; F --> G["製造実行"]; G --> H["製造実績"]; H --> I["完成品在庫"];

午後試験では、これらの業務フローを正確に理解し、データ間の依存関係や整合性を考慮したデータモデルを構築できるかが問われます。特に、在庫管理や原価計算といった側面とデータベース設計を結びつける問題が出題されることがあります。


第6章 業務知識 問題集 (20問)


問題 1 (販売管理のプロセス順序)

一般的な販売管理の一連の業務プロセスにおいて、「受注」の次に発生する業務として最も適切なものはどれか。

ア. 見積
イ. 請求
ウ. 出荷指示
エ. 入金

解答と解説

解答: ウ

解説:
販売管理の一般的なプロセスは「見積 → 受注 → 出荷指示 → 出庫指示・実績 → 出荷実績 → 請求 → 入金」の順に進みます。受注が確定した後、倉庫に出荷を依頼するための「出荷指示」が出されます。


問題 2 (見積管理のエンティティ)

「見積(Quotation)」業務において、主要な情報を管理するために最低限必要なエンティティの組み合わせとして適切なものはどれか。

ア. 顧客、製品、注文
イ. 顧客、製品、見積、見積明細
ウ. 製品、出荷指示、請求
エ. 従業員、製品、見積

解答と解説

解答: イ

解説:
見積は顧客と製品を対象に行われるため、顧客情報、製品情報、そして見積書そのものの情報(見積)とその詳細(見積明細)が必要となります。注文は受注業務以降に発生するエンティティです。


問題 3 (受注と見積のリレーションシップ)

「顧客からの注文は、必ず以前に提示された見積に基づいて行われる」という業務ルールがある場合、注文 (Order)エンティティと見積 (Quotation)エンティティ間のリレーションシップの多重度と任意性として最も適切なものはどれか。

ア. 注文(多) - 見積(1) (必須)
イ. 注文(1) - 見積(1) (必須)
ウ. 注文(多) - 見積(1) (注文は見積に対して必須、見積は注文に対して任意)
エ. 注文(1) - 見積(多) (必須)

解答と解説

解答: ア

解説:
「顧客からの注文は、必ず以前に提示された見積に基づいて行われる」ということは、「1つの注文は必ず1つの見積から来る(注文→見積が必須で1)」ことを意味します。 「1つの見積からは、複数の注文が発生する可能性がある」と考えるのが自然なので、「見積→注文が任意で多」となります。 したがって、「注文(多) - 見積(1)」で、注文側から見積側への関連は必須です。


問題 4 (出庫指示と出庫実績)

「出庫指示」と「出庫実績」の業務において、指示数量と実際数量の両方を記録することが重要な理由を簡潔に説明しなさい。

解答と解説

解答:
指示数量と実際数量の両方を記録することで、ピッキング作業における過不足や間違いを把握し、在庫差異の原因特定や作業品質の評価に役立てることができます。また、顧客への出荷情報との突合や、在庫管理の正確性を保つためにも重要です。


問題 5 (請求業務のトリガー)

販売管理において、請求業務が開始される典型的なきっかけ(トリガー)となる業務は何か。

ア. 見積が承認された時
イ. 注文が確定された時
ウ. 製品の出荷が完了した時
エ. 入金が確認された時

解答と解説

解答: ウ

解説:
一般的に、請求書は商品やサービスが顧客に提供され、出荷が完了したことを確認した後で発行されます。


問題 6 (生産管理のトリガー)

生産管理において、製品の製造を行うきっかけとなる「需要予測」以外に、考えられるトリガーを1つ挙げなさい。

解答と解説

解答例:

  1. 顧客からの受注: 顧客からの具体的な注文に基づいて製造を開始する(受注生産)。
  2. 在庫補充: 製品や部品の在庫が安全在庫レベルを下回った際に、在庫を補充するために製造を開始する。
  3. 他部門からの依頼: 修理用部品や社内設備用の部品など、製造部門以外の部門からの依頼。

問題 7 (品目)

生産管理で扱う「品目(Item)」には、通常どのような種類の「モノ」が含まれるか。適切なものをすべて選択しなさい。

ア. 完成品
イ. 半製品
ウ. 部品
エ. 原材料
オ. サービス

解答と解説

解答: ア, イ, ウ, エ

解説:
生産管理における品目は、製造に関わる全ての物理的な「モノ」を指します。完成品、半製品、部品、原材料などが該当します。サービスは物理的なモノではないため、通常は品目としては扱われませんが、品目として管理される完成品に付随するサービスとして管理されることはあります。


問題 8 (部品構成表)

「部品構成表(BOM)」が生産管理において果たす最も重要な役割は何か。

ア. 製品の価格を決定するため。
イ. 完成品を製造するために必要な部品の種類と数量を示すため。
ウ. 従業員の勤務時間を管理するため。
エ. 顧客からのクレーム情報を記録するため。

解答と解説

解答: イ

解説:
部品構成表(BOM)は、ある製品がどのような部品や原材料から構成されているか、そしてそれぞれがどれだけ必要かを示すリストであり、所要量展開(MRP)の基礎となります。


問題 9 (所要量展開 - MRP)

「所要量展開(MRP)」の主な目的は何か。簡潔に説明しなさい。

解答と解説

解答:
所要量展開(MRP)の主な目的は、完成品の生産計画や受注量に基づいて、それを製造するために必要な部品や原材料の「必要量」と「いつまでに必要か(必要時期)」を正確に計算することです。これにより、過剰な在庫や部品不足を防ぎ、生産計画を最適化します。


問題 10 (製造指図)

「製造指図(Production Order)」は、生産管理のどの段階で発行されるか。

ア. 顧客からの受注時
イ. 部品構成表の作成時
ウ. 所要量展開(MRP)の結果に基づいて
エ. 完成品の出荷時

解答と解説

解答: ウ

解説:
所要量展開(MRP)によって、どのような製品や部品をどれだけ製造する必要があるかが明確になった後、具体的な製造作業を指示するために製造指図が発行されます。


問題 11 (発注と入荷)

生産管理における「発注」業務で作成される主なエンティティは何か。また、そのエンティティが参照する主なエンティティも挙げなさい。

解答と解説

解答:


問題 12 (販売管理 - 注文と注文明細)

注文 (Order)エンティティと注文明細 (OrderDetail)エンティティのリレーションシップは、一般的にどのような多重度になるか。

ア. 注文(1) - 注文明細(1)
イ. 注文(1) - 注文明細(多)
ウ. 注文(多) - 注文明細(1)
エ. 注文(多) - 注文明細(多)

解答と解説

解答: イ

解説:
1つの注文は複数の製品を含む注文明細を持つことができ、1つの注文明細は必ず1つの注文に属します。したがって、1対多(Order:1 - OrderDetail:N)の関係となります。


問題 13 (生産管理 - 部品構成の階層表現)

製品Aが部品Bと部品Cから構成され、部品Bは部品Dから構成される階層構造を持つ場合、この部品構成表をデータベースで表現するために必要な主要なエンティティとその関係について簡潔に説明しなさい。

解答と解説

解答:
主要なエンティティは品目 (Item)部品構成 (BillOfMaterial)です。 Itemテーブルが全ての部品や製品の基本情報を持ち、BillOfMaterialテーブルが親品目ID子品目ID使用数量などの情報を持つことで、Item間の自己参照リレーションシップを通じて階層構造を表現します。


問題 14 (販売管理 - 出荷実績の記録内容)

出荷実績(ShippingRecord)エンティティに記録される情報として、主要なものを2つ挙げなさい。

解答と解説

解答例:

  1. 実際出荷日時: 実際に製品が出荷された日時。
  2. 配送業者: 製品を配送した運送業者の情報。
  3. 追跡番号: 荷物の追跡に使用する番号。
  4. 出荷実績ID: 出荷実績を一意に識別するID。

問題 15 (生産管理 - 入荷と発注のリレーションシップ)

「1つの発注に対して複数の入荷実績がある場合があり、1つの入荷実績は必ず1つの発注に対するものである」という業務ルールがある場合、入荷 (GoodsReceipt)エンティティと発注 (PurchaseOrder)エンティティ間のリレーションシップの多重度と任意性として最も適切なものはどれか。

ア. 入荷(多) - 発注(1) (必須)
イ. 入荷(1) - 発注(多) (必須)
ウ. 入荷(多) - 発注(1) (入荷は発注に対して必須、発注は入荷に対して任意)
エ. 入荷(1) - 発注(多) (入荷は発注に対して任意、発注は入荷に対して必須)

解答と解説

解答: ア

解説:
「1つの入荷実績は必ず1つの発注に対するもの」なので、入荷側から発注側への関連は必須で1。「1つの発注に対して複数の入荷実績がある場合がある」ので、発注側から入荷側への関連は多(かつ発注にまだ入荷がない可能性があるので任意)。 結果として「入荷(多) - 発注(1)」で、入荷から発注への関連が必須となります。


問題 16 (販売管理 - 顧客エンティティの属性)

顧客 (Customer)エンティティが持つべき主要な属性を3つ挙げなさい。

解答と解説

解答例:

  1. 顧客ID: 顧客を一意に識別するための主キー。
  2. 顧客名: 顧客の氏名または会社名。
  3. 住所: 顧客の連絡先住所。
  4. 電話番号: 顧客の連絡先電話番号。
  5. メールアドレス: 顧客の連絡先メールアドレス。

問題 17 (生産管理 - 製造指図の目的)

製造指図(ProductionOrder)の主な目的は何か。簡潔に説明しなさい。

解答と解説

解答:
製造指図は、所要量展開(MRP)の結果に基づいて、特定の製品や部品を、いつまでに、どれだけ製造すべきかを製造現場に具体的に指示するための業務指示書です。製造の実行管理、進捗管理、および実績記録の基礎となります。


問題 18 (午後問題対策 - 業務知識)

データベーススペシャリスト試験の午後Ⅱ問題では、業務知識をどのように活用する能力が問われるか、簡潔に説明しなさい。

解答と解説

解答:
午後Ⅱ問題では、与えられた複雑な業務記述を正確に読み解き、その業務の流れやルールを理解した上で、適切なエンティティ、属性、リレーションシップを抽出し、データモデル(E-R図や関係スキーマ)として表現する能力が問われます。単なるデータベースの技術知識だけでなく、ビジネスプロセスをデータとしてどのように捉えるかが重要となります。


問題 19 (販売管理 - 在庫との関連)

販売管理において、受注が発生した際と出荷が発生した際で、製品在庫数に与える影響はそれぞれどのように処理されるべきか。

解答と解説

解答:


問題 20 (生産管理 - 発注の自動化)

生産管理において、発注業務を自動化するための情報として、品目 (Item)エンティティが持つべき属性と、所要量計画 (MRPPlan)エンティティが持つべき属性をそれぞれ1つずつ挙げなさい。

解答と解説

解答: