BIGFILE 表領域の縮小機能を試す（Oracle Database 23ai）

Oracle Database 23ai の新機能である BIGFILE 表領域のオンライン縮小機能について検証します。

# 表領域データファイルの最大サイズ
Oracle Database の表領域は複数のファイル（ファイルシステム上のファイル）から構成されます。表領域を構成するデータファイルは、表領域作成時に BIGFILE と SMALLFILE を選択できます。デフォルト値はデータベース作成時のオプションで決まります。データベース作成時に何も指定しない場合は SMALLFILE がデフォルトになります。SMALLFILE 表領域の場合、約 400 万ブロックを単一ファイルに格納できます。このため、ブロックサイズ（db_block_size）がデフォルトの 8 KB の場合、SMALLFILE データファイルの最大サイズは約 32 GB になります。BIGFILE データファイルは単一ファイルに約 40 億ブロックを格納できます。BIGFILE データファイルの最大サイズは約 16 TB になります。ただし BIGFILE を指定した表領域は単一ファイルで構成する必要があります。

```SQL: 表領域の作成
SQL> CREATE TABLESPACE small1 DATAFILE '+DATA1' SIZE 100M, '+DATA2' SIZE 100M;

表領域が作成されました。

SQL> CREATE BIGFILE TABLESPACE big1 DATAFILE '+DATA1' SIZE 100M;

表領域が作成されました。
```

上記の例では SMALLFILE 表領域 small1 と BIGFILE 表領域 big1 を作成しています。small1 表領域は複数ファイルから構成されていますが、big1 表領域は単一ファイルのみ許可されます。


# BIGFILE 表領域の縮小
　従来のバージョンでは BIGFILE 表領域を構成するデータファイルは [ALTER TABLESPACE RESIZE 文](https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/ALTER-TABLESPACE.html)でサイズの変更を行いました。しかしこの構文を利用できるのは消失書込み保護トラッキング・データを格納する表領域の場合のみでした。

Oracle Database 19c の[ALTER TABLESPACE文のマニュアル](https://docs.oracle.com/cd/F19136_01/sqlrf/ALTER-TABLESPACE.html)から
> この句は、消失書込み保護トラッキング・データを格納するシャドウ表領域などのbigfile表領域に対してのみ有効です。1つのデータファイルのサイズを指定のサイズまで拡張または縮小できます。K、M、GまたはTを使用して、それぞれKB、MB、GBまたはTB単位で指定することもできます。
  
　ALTER TABLESPACE RESIZE 文では表領域に格納されたオブジェクトは変更されず、使用していない部分のみを縮小できます。
  
```SQL: ALTER TABLESPACE 文によるファイルの縮小
SQL> ALTER TABLESPACE big1 RESIZE 10M;
ALTER TABLESPACE big1 RESIZE 100M
*
行1でエラーが発生しました。:
ORA-03297:
ファイルには、リクエストしたRESIZE値を超える使用中のデータが含まれてい ます。

SQL> ALTER TABLESPACE big1 RESIZE 900M;

表領域が変更されました。
```

  Oracle Database 23c では [DBMS_SPACE パッケージ](https://docs.oracle.com/en/database/oracle/oracle-database/23/arpls/DBMS_SPACE.html)の SHRINK_TABLESPACE プロシージャを使ってオブジェクトの再編成を行いながらオンライン状態でサイズの縮小を実行できるようになりました。
 
DBMS_SPACE.SHRINK_TABLESPACE プロシージャの構文は以下の通りです。

```SQL: SHRINK_TABLESPACE プロシージャ
DBMS_SPACE.SHRINK_TABLESPACE(
  ts_name IN VARCHAR2,
  shrink_mode IN NUMBER,
  target_size IN NUMBER, 
  shrink_result OUT CLOB)

DBMS_SPACE.SHRINK_TABLESPACE(
  ts_name IN VARCHAR2,
  shrink_mode IN NUMBER,
  target_size IN NUMBER) 
```

shrink_mode パラメーターには以下のモードが使用できます。

|モードを示す定数|説明|備考|
|:---|:---|:---|
|TS_MODE_ANALYZE|縮小可能か分析を行う||
|TS_MODE_SHRINK|オンラインでオブジェクトを移動し、データファイルの縮小を行う|デフォルト|
|TS_MODE_SHRINK_FORCE|オンラインでオブジェクトの移動に失敗するとオフラインで縮小を行う||

　target_size パラメーターにはバイト単位でサイズを指定します。デフォルト値は定数 TS_TARGET_MAX_SHRINK です。この値は可能な限り小さいサイズに縮小します。

## 確認
　SHRINK_TABLESPACE プロシージャを TS_MODE_ANALYZE 定数を指定して実行すると表領域データファイルを縮小処理した場合のサイズを分析できます。

```SQL: 縮小の確認
SQL> SET SERVEROUTPUT ON
SQL> EXECUTE DBMS_SPACE.SHRINK_TABLESPACE('BIG1', DBMS_SPACE.TS_MODE_ANALYZE);

PL/SQLプロシージャが正常に完了しました。

SQL> SET SERVEROUTPUT ON
SQL> EXECUTE DBMS_SPACE.SHRINK_TABLESPACE('BIG1', DBMS_SPACE.TS_MODE_ANALYZE);
-------------------ANALYZE RESULT-------------------
Total Movable Objects: 0
Total Movable Size(GB): 0
Original Datafile Size(GB): .1
Suggested Target Size(GB): .04
Process Time: +00 00:00:00.250320

PL/SQLプロシージャが正常に完了しました。

SQL> SELECT bytes/1024/1024 mb FROM dba_data_files WHERE tablespace_name='BIG1';

        MB
----------
      1024
```


## 実行
  実際に表領域を縮小する場合は SHRINK_TABLESPACE プロシージャのshrink_mode パラメーターに定数 TS_MODE_SHRINK を指定して実行します。

```SQL: 縮小の実行
SQL> SET SERVEROUTPUT ON
SQL> EXECUTE DBMS_SPACE.SHRINK_TABLESPACE('BIG1', DBMS_SPACE.TS_MODE_SHRINK);
-------------------SHRINK RESULT-------------------
Total Moved Objects: 0
Total Moved Size(GB): 0
Original Datafile Size(GB): 1
New Datafile Size(GB): .01
Process Time: +00 00:00:00.868811

PL/SQLプロシージャが正常に完了しました。

SQL> SELECT bytes/1024/1024 mb FROM dba_data_files WHERE tablespace_name='BIG1';

        MB
----------
     6.125
```

target_size パラメーターに値を指定しない場合は定数 TS_TARGET_MAX_SHRINK が使用され、データファイルは可能な限り小さいサイズに縮小されます。

Author: Noriyoshi Shinoda / Date: August 14, 2024