【Oracle DB】表領域（TABLESPACE）についてまとめてみる

## はじめに

  現在、Oracle Silver DBAの学習を進めている中で、**表領域** という概念にぶち当たりました。  

  合格を目的とするならそのまま暗記してもいいんですが、今回「SQL」ではなく **「DBA」** を選択した目的としてアーキテクチャやこういった概念を理解したかった、というものがあったので、向き合ってみようと思います。

  使用している参考書は[オラクルマスター教科書 Silver DBA Oracle Database Administration I](https://www.amazon.co.jp/%E3%82%AA%E3%83%A9%E3%82%AF%E3%83%AB%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%BC%E6%95%99%E7%A7%91%E6%9B%B8-Silver-Oracle-Database-Administration/dp/4798166359/ref=pd_lpo_d_sccl_1/355-4986059-0425665?pd_rd_w=WbxbD&content-id=amzn1.sym.855d8f70-df76-4181-80b0-56e48ae3bb9b&pf_rd_p=855d8f70-df76-4181-80b0-56e48ae3bb9b&pf_rd_r=4J3P9MW23BE4XKRFSPJ2&pd_rd_wg=11F4O&pd_rd_r=e6f6c7fc-b54a-4766-8d44-4c192520cfa7&pd_rd_i=4798166359&psc=1)です。
  今回もここからまとめさせていただいております。
  
  ※誤りありましたら、ご指摘いただけますと幸いです。

## 表領域とは
  簡単に言うと **データファイルを論理的にグループ化した概念** のことを指します。
  ※データファイルとは、名前の通りデータを格納するファイルのことで、オブジェクト（表や索引）が格納されます。  
      
  オブジェクトを作成する際、格納先が必要なわけですが、これらの格納先として指定されるのは、データファイルではありません。
  ここで格納先として指定されるのは、**表領域** というわけです。  

  表領域は、1つ以上のデータファイルをグループ化したものを指します。オブジェクトの記憶域は、そのオブジェクトの格納先として指定された表領域を構成するデータファイルから割り当てられます。
  
  文字だけだと理解しづらいと思うので、イメージしやすくするために図でまとめてみました。

### オブジェクトに記憶域を割り当てる仕組みとは
  下記図を基に説明してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715906/246b3a0a-ff34-128d-c013-fd42fc30f69c.png)
  

  - 左から、「オブジェクト」「表領域」「データファイル」と並んでいます。  

  - オブジェクトは、表領域内で保管されている **セグメント** と1対1で紐づきます。   

  - セグメントは、1つ以上の **エクステント**　で構成されています。
    - 図の中では水色や黄色等色付きで分けられているのがエクステント
    - セグメントに空き領域が不足した場合は、エクステントを追加することが可能 

  - エクステントは、 **連続した複数のデータブロック** で構成されています。 
    - 図の中ではデータファイル内の小さい四角一つひとつがデータブロック
    - 実際のデータはこのデータブロック内に保管される
    - 見て分かる通り、データブロック1つでは容量が小さく効率が悪いため、複数のデータブロックを **エクステント** としてまとめ、このエクステントを **セグメント** に割り当てる形になる


  大まかに、上記のように記憶域は割り当てられています。  
  上で説明したように、オブジェクトを格納する際は、データファイルを直接指定するのではなく、表領域が割り当てられていることが確認できたかと思います。
  

## 表領域の種類
  表領域には、格納できるセグメントによって以下3種類に分けられます。

  1. **永続表領域**  
      - 一般的に言う通常の表領域のことで、表や索引等、オブジェクトを格納
      - アプリケーション用のデータを格納する通常の永続表領域と特殊な役割の永続表領域に分類される
      - 特殊な役割の永続表領域は **SYSTEM表領域** と **SYSAUX表領域** の２つに分けられ、**SYSTEM表領域** はDBの重要な管理情報を格納し、 **SYSAUX表領域** はSYSTEM表領域の補助的な役割を担う


  2. **UNDO表領域**
      - **UNDOセグメント** と呼ばれる過去のデータを保持する特殊なセグメントを格納するために使用される 
      - ちなみに、永続表領域で格納できた表や索引等のオブジェクトは格納できない

  3. **一時表領域** 
      - **一時セグメント** と呼ばれる一時的なデータを保持する特殊なセグメントを格納するために使用される
      - こちらもUNDO表領域同様、表や索引等のオブジェクトは格納できない



## エクステントの管理方式  
  エクステントの内部管理方式は、2つに分けられます。

  1. **ローカル管理方式**
      - 各表領域の管理用ブロックでエクステントを管理するため、高速に管理できる
      - エクステントのサイズは自動で決定
      - 空き領域の断片化も発生しにくい


  2. ディクショナリ管理方式  
      - SYSTEM表領域のデータディクショナリでエクステントを管理
      - エクステントのサイズは手動で決定
      - 空き領域の断片化も発生しやすい


  上記から見て分かるように、ディクショナリ方式はローカル方式の下位互換として存在するのみで、実際に運用されているOracleデータベースのほぼすべてで **ローカル管理方式** が採用されているようです。  

  将来的には、ディクショナリ方式は非推奨となるみたいです。

  ### ローカル管理方式でできること
  ローカル管理方式では下記の機能を使用可能です。

  - エクステント割り当ての自動化
    - 新たにセグメントを作成した際や、セグメントのサイズ拡張時のサイズを、Oracleが自動で決定する
    - 管理者が設定する必要がない

  - 自動セグメント領域管理
    - セグメント内のブロックの空き状態の管理に関わる内部処理を、Oracleが自動化してくれる
    - 管理者が調整する必要がない
    - サイズの決定方法には **AUTOALLOCATE（サイズは自動で決定）** と **UNIFORM（サイズは固定）** がある

  - bigfile表領域
    - 非常に大きなサイズのデータベースを想定した機能で、データファイルの最大サイズは **32TB**
    - Oracle10gから採用された

  - 遅延セグメント作成
    - オブジェクト作成時にセグメントを作成しない機能
    - INSERTされたタイミングで初めてセグメントが作成される
    - データが格納されない可能性がある表が大量に存在する場合に領域消費を大幅に抑えられるというメリットがある

  - セグメント縮小
    - セグメントに格納されたデータが削除された際に、セグメントを縮小できる
    - 詳細は割愛しますが、セグメントの格納効率が向上し、処理が効率化される
  

## 表領域の作成
  最後に、表領域の作成方法について説明します。

  1. 永続表領域の作成
  ```sql
  CREATE TABLESPACE tbs01 
  DATAFILE '/usr/file/path/tbs01.dbf' 
  SIZE 100M 
  AUTOEXTEND ON;
  ``` 
  「CREATE TABLESPACE」で作成が可能です。
  ファイルパスや初期サイズ、エクステントの割り当て方式も指定できます。

  2. UNDO表領域の作成
  ```sql
  CREATE UNDO TABLESPACE undotbs01 
  DATAFILE '/usr/file/path/undotbs01.dbf' 
  SIZE 100M;
  ``` 
  「CREATE UNDO TABLESPACE」で作成が可能です。
  UNDO表領域のエクステント割り当て方式は「AUTOALLOCATE」となり「UNIFORM」にはできません。

  3. 一時表領域の作成
  ```sql
  CREATE TEMP TABLESPACE temptbs01 
  DATAFILE '/usr/file/path/temptbs01.dbf' 
  SIZE 100M;
  ``` 
  「CREATE TEMP TABLESPACE」で作成が可能です。
  一時表領域のエクステント割り当て方式は「UNIFORM」となり「AUTOALLOCATE」にはできません。

## 最後に
  普段何気なく作成しているテーブルやDBの裏側を知ることができて非常に勉強になっています。  

  ちなみに、現在学習している参考書は合計 **850ページ** くらいあるのですが、その中で、今回取り扱った内容は僅か **8ページ** 程度です。  

  普段何気なく使っているDBがどれだけ奥深いものかを毎日痛感していますが、どの現場でも付き合うことになるのもまたDBだと思うので、しっかり向き合って資格も取得できたらと思います。