Oracle データ構造まとめ

### 1.はじめに
Oracleのデータ構造は、複雑なようでシンプルでもあるという印象を持っています。勉強しているときに覚えたことも、しばらくすると忘れてしまうことが私にはあります。

なので、学習した内容を細かくChatGPT先生に質問しながら、視覚的に分かりやすくして、明日の自分が覚えていられるようにまとめました。

### 2.領域一覧
ChatGPT先生（以下先生）に、「Oracleにある領域やプロセスを図にして～～～」と依頼したところ、以下の回答をもらいました。
先生の言うことなので正確だと思いますが、確認してみたところやはり正しいようです。

```sqss
Oracle データベース全体
├── 表領域 (Tablespaces)
│   ├── データ表領域 (Data Tablespaces) - 必須
│   │   ├── データ・セグメント (Data Segments) - 必須
│   │   │   ├── エクステント (Extents) - 必須
│   │   │   │   ├── データブロック (Data Blocks) - 必須
│   ├── インデックス表領域 (Index Tablespaces) - 非必須
│   │   ├── インデックス・セグメント (Index Segments) - 必須（インデックス作成時）
│   │   │   ├── エクステント (Extents) - 必須
│   │   │   │   ├── データブロック (Data Blocks) - 必須
│   ├── 一時表領域 (Temporary Tablespaces) - 必須（一時データ用）
│   │   ├── 一時セグメント (Temporary Segments) - 必須（一時操作用）
│   │   │   ├── エクステント (Extents) - 必須
│   │   │   │   ├── データブロック (Data Blocks) - 必須
│   ├── UNDO 表領域 (Undo Tablespaces) - 必須
│       ├── UNDO セグメント (Undo Segments) - 必須
│       │   ├── エクステント (Extents) - 必須
│       │   │   ├── データブロック (Data Blocks) - 必須
├── 制御ファイル (Control Files) - 全体で一つまたは複数、必須
├── レド(リドゥ)ログファイル (Redo Log Files) - 全体で一つまたは複数、必須
└── データディクショナリ (Data Dictionary) - データベース全体に一つ、必須
```

というわけで、以下のファイルを理解する必要があります。それぞれについて[2-X]章で記載しています。特にエクステントとインデックスが難しかったので、先生と何十回もやり取りをして内容をまとめました。良い先生です。

1. 表領域 (Tablespaces) 
1. データ・セグメント (Data Segments)
1. エクステント (Extents) 
1. データブロック (Data Blocks) 
1. インデックス表領域 (Index Tablespaces) 
1. 一時表領域 (Temporary Tablespaces) 
1. UNDO セグメント (Undo Segments) 
1. 制御ファイル (Control Files) 
1. レド(リドゥ)ログファイル (Redo Log Files) 
1. データディクショナリ (Data Dictionary)

#### 2-1 表領域 (Tablespaces)
実際のデータが格納されるファイルです。以下は実際のデータが格納されるファイルである表領域（Tablespaces）の作成と確認のSQL例です。

```sql:表領域 (Tablespaces)作成SQLの例
CREATE TABLESPACE users DATAFILE 'users01.dbf' SIZE 100M AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED;
```

```sql:表領域 (Tablespaces)確認SQLの例
SELECT TABLESPACE_NAME, STATUS FROM DBA_TABLESPACES;
```

#### 2-2 データ・セグメント (Data Segments)
具体的なデータオブジェクト（テーブルなど）が格納される場所です。
表領域の中に配置され、実際のデータが保存される領域です。以下は、テーブルを作成した時にデータセグメントが使用される例です。
表領域の中にデータセグメントのテーブルがある感じです。

```sql:table作成SQLの例
CREATE TABLE employees (
    id NUMBER PRIMARY KEY,
    name VARCHAR2(100),
    salary NUMBER
) TABLESPACE users;
```

```sql:table検索SQLの例
SELECT OWNER, SEGMENT_NAME, SEGMENT_TYPE, TABLESPACE_NAME FROM DBA_SEGMENTS WHERE SEGMENT_TYPE = 'TABLE';
```

#### 2-3 エクステント (Extents)
先生10ラリーくらいした箇所です。良い先生です。
 - エクステントは、データセグメント（例えば、テーブルやインデックスなど）の一部であり、データが追加されると新しいエクステントが割り当てられる
- エクステントは連続したデータブロックの集合であり、データが分散せずに連続した領域に保存されるため、ディスクI/Oのパフォーマンスが向上する
- エクステントがないと、データベースはデータブロックを効率的に管理することができず、データがディスク上で散らばって保存されることになる

#### 2-4 データブロック (Data Blocks)
Oracleデータベースの最小のデータ格納単位。複数並んで集まったものがエクステントになります。

#### 2-5 インデックス表領域 (Index Tablespaces)
先生と何十回もラリーしました。良い先生です。
データ検索の効率化を行うための領域です。以下のデータが格納されます。

1. インデックスキー
内容: インデックスが作成される列の値。たとえば、employees テーブルの name 列にインデックスを作成した場合、その列の各値（例: 'Alice', 'Bob' など）がインデックスキーとして使われます。

2. ROWID
内容: 各インデックスキーに関連付けられた、テーブル内の対応する行を指し示す物理アドレスです。

3. ブランチブロック（Bツリーインデックスの場合）
インデックスの中間層を構成するブロックで、下層へのポインタ（次のブロックへのリンク）を含みます。

4. リーフブロック
インデックスの最下層を構成するブロックで、実際のインデックスキーとROWIDが格納されています。

検索プロセス:
以下のように検索されるため、リーフブロックを利用する分、全件検索より早くなります。
1. ルートブロック: インデックスのルートブロックから検索を開始
2. ブランチブロック1または2: 'Flank'はアルファベット順で後半にあるため、ルートブロックはブランチブロック2へのポインタを指す
3. リーフブロック2: ブランチブロック2内で検索を続け、最終的にリーフブロック2に到達する。ここで、'Flank'というインデックスキーと対応するROWID（AAAC6F）が見つかりる
4. データの取得: ROWIDを使用して、実際のテーブルから'Flank'の行データを迅速に取得する

 - インデックスキーとROWIDの例

|インデックスキー (Name)|	ROWID
| ---- | ---- |
Alice|	AAAC1A
Bob|	AAAC2B
Charlie|	AAAC3C
Dave |	AAAC4D
Ellen|	AAAC5E
Frank|	AAAC6F


 - ブランチブロック1

|ブランチブロック1|	子ブロックへのポインタ（リーフブロック）|
| ---- | ---- |
Alice|	リーフブロック1へのポインタ
Bob|	リーフブロック1へのポインタ
Charlie|	リーフブロック1へのポインタ

 - ブランチブロック2

|ブランチブロック2|	子ブロックへのポインタ（リーフブロック）|
| ---- | ---- |
Dave|	リーフブロック2へのポインタ
Ellen|	リーフブロック2へのポインタ
Frank|	リーフブロック2へのポインタ

 - リーフブロック
 
|リーフブロック1	|インデックスキー (Name)	|ROWID
| ---- | ---- | ---- |
Alice|	Alice|	AAAC1A
Bob|	Bob|	AAAC2B
Charlie|	Charlie|	AAAC3C

|リーフブロック2	|インデックスキー (Name)|	ROWID|
| ---- | ---- | ---- |
Dave|	Dave|	AAAC4D
Ellen|	Ellen|	AAAC5E
Frank|	Frank|	AAAC6F

次に新しい従業員「Andrew」が追加された場合です。
インデックスに新しいインデックスキー「Andrew」が追加されます。Bツリーインデックスは常にソート順を保つため、新しいキーを適切な位置に挿入されます。

 - ブランチブロック1の更新

|ブランチブロック1|	子ブロックへのポインタ（リーフブロック）|
 ---- | ---- |
Alice|	リーフブロック1へのポインタ
**Andrew** |	リーフブロック1へのポインタ
Bob|	リーフブロック1へのポインタ
Charlie|	リーフブロック1へのポインタ

ブランチブロック2
|ブランチブロック2|	子ブロックへのポインタ（リーフブロック）|
| ---- | ---- |
Dave|	リーフブロック2へのポインタ
Ellen|	リーフブロック2へのポインタ
Frank|	リーフブロック2へのポインタ


 - リーフブロック1の更新

|リーフブロック1|	インデックスキー (Name)|	ROWID
| ---- | ---- | ---- |
Alice|	Alice |	AAAC1A
**Andrew**|	Andrew |	AAAC1B
Bob|	Bob|	AAAC2B
Charlie|	Charlie|	AAAC3C

 - リーフブロック2

|リーフブロック2|	インデックスキー (Name)	ROWID
| ---- | ---- |
Dave|	Dave|	AAAC4D
Ellen|	Ellen|	AAAC5E
Frank|	Frank|	AAAC6F

#### 2-6 一時表領域 (Temporary Tablespaces) 
一時的なデータベース操作に使用されるデータを保存します。以下などが含まれます：
 ・ソートデータ: クエリ処理中の大量データのソート領域
 ・一時的なクエリ結果: 複雑なクエリからの中間結果

#### 2-7 UNDO セグメント (Undo Segments)
UNDOセグメントは、データベース操作を取り消すために使用されるデータを格納されます。

- INSERT文が実行された場合:
新しい行がテーブルに挿入されますが、UNDOセグメントにはその新しい行の削除情報が記録されます。
トランザクションをロールバックする際に、新しい行を削除するための情報が格納されます。

- UPDATE文が実行された場合:
行のデータが更新されるが、UNDOセグメントには更新前の元のデータが記録されます。
トランザクションをロールバックする際に、行を元の状態に戻すための情報が格納されます。

- DELETE文が実行された場合:
行がテーブルから削除されるますが、UNDOセグメントには削除された行の元のデータが記録されます。
トランザクションをロールバックする際に、削除された行を復元するための情報が格納されます。

```sql
SELECT SEGMENT_NAME FROM DBA_SEGMENTS WHERE SEGMENT_TYPE='UNDO';
```

#### 2-8 制御ファイル (Control Files)
制御ファイルはデータベースの非常に重要なファイルで、データベースの構造に関する情報を含んでいます。具体的には、以下のような情報が含まれます。
- データベース名
- データベースが作成された日時
- データファイルとレドログファイルの場所とサイズ

#### 2-9 レド(リドゥ)ログファイル (Redo Log Files)
データベースのすべての変更を記録し、障害時のリカバリに使用される。

 - INSERT文が実行された場合:
新しい行がテーブルに挿入されたことが記録されます。
REDOログには、この新しい行のデータが含まれます。

 - UPDATE文が実行された場合:
行のデータが更新されたことが記録されます。
REDOログには、更新後のデータが含まれます。

 - DELETE文が実行された場合:
行がテーブルから削除されたことが記録されます。
REDOログには、削除された行の識別情報が含まれます。

#### 2-10 データディクショナリ (Data Dictionary)
データディクショナリは、データベースのメタデータを格納するシステムテーブルとビューの集合です。以下のような情報が含まれています：
- テーブル、ビュー、インデックスなどのオブジェクトの定義
- 各オブジェクトの権限やアクセス権
- データベースのスキーマ情報

#### おまけ
起動状態との関係性

 - NOMOUNT:
データベースのパラメータファイルのみが読み込まれまれる。

 - MOUNT:
制御ファイルが読み込まれ、データベースの構造に関するメタデータが確認される。

```sql
ALTER DATABASE MOUNT;
```

 - OPEN:
データベースが利用可能になり、ユーザーがデータにアクセスできるようになります。

```sql
ALTER DATABASE OPEN;
```
データディクショナリ、各種セグメント、UNDOデータ、REDOログが活用されます。

 - SHUTDOWN:
データベースを安全に終了させるために使用されます。
このプロセスでは、まずユーザートランザクションとサーバープロセスが終了され、次にバックグラウンドプロセスが停止し、最後にデータファイルとレドログファイルが閉じられます。

```sql
SHUTDOWN IMMEDIATE;
```