はじめに
Oracle Autonomous AI Database には、オブジェクト・ストレージ上のデータレイクを効率よく照会するための仕組みが複数用意されています。その中でも 2024年10月に追加された Implicit Partitioning for External Tables(外部表の暗黙パーティション) は、データレイクのクエリ性能を大幅に向上させる新機能です。
この機能は、オブジェクト・ストレージ上のフォルダ階層(例:/sales/country=USA/year=2024/month=01/)を自動的に検出し、外部表の 仮想列(Virtual Column) として取り込みます。これにより、SQL クエリで MONTH = '01' のような条件を指定するだけで、不要なディレクトリ・ファイルを読み飛ばす パーティション・プルーニング が自動的に機能します。
従来の外部表パーティションと比べて最大の利点は、メンテナンスや同期が不要 な点です。オブジェクト・ストレージ側でディレクトリやファイルが追加・変更されても、Autonomous Database 側は自動的に変更を反映します。パーティション構造はデータベース・ディクショナリには保存されず、クエリ実行時にランタイムで検出されます。
サポートされるディレクトリ構造の種類は次のとおりです。
| タイプ | 説明 | ディレクトリ構造の例 |
|---|---|---|
| Hive スタイル |
キー=値 形式のディレクトリ名。自動的に列名を認識します。 |
/sales/country=USA/year=2024/month=01/ |
| 非 Hive スタイル | キー名のない階層構造。列名は外部表定義で指定します。 | /sales/USA/2024/01/ |
この記事では Hive スタイル の暗黙パーティションを検証します。
事前準備
- Oracle Autonomous AI Database Serverless(ADB-S)のインスタンス
- DBMS_CLOUD パッケージが利用可能であること(ADB-S では標準で提供)
- データベース・ユーザーが
DBMS_CLOUD.CREATE_EXTERNAL_TABLEを実行できる権限を持っていること - オブジェクト・ストレージへのアクセスに使用する クレデンシャル(Credential) が作成済みであること
- DBMS_CLOUD クレデンシャルの作成(DBMS_CLOUD リファレンス )
- 外部表対象のファイルをオブジェクト・ストレージ(OCI Object Storage 等)に格納済みであること
- サポートされるファイル形式:Parquet、CSV など DBMS_CLOUD.CREATE_EXTERNAL_TABLE がサポートする形式
手順
Step 1: オブジェクト・ストレージのフォルダ構造を確認
この記事で使用するサンプルデータは、売上データ(custsales)です。国・年・月をHive スタイルで以下のように 3 階層のパーティション構造になっています。
custsales/
├── country=US/
│ ├── year=2023/
│ │ ├── month=01/
│ │ │ └── *.parquet
│ │ └── month=02/
│ │ └── *.parquet
│ └── year=2024/
│ └── month=01/
│ └── *.parquet
├── country=JP/
│ └── year=2024/
│ └── month=01/
│ └── *.parquet
└── ...
この例では country、year、month の 3 列が仮想列として自動認識されます。
Step 2: 外部表を作成
implicit_partition_type パラメータに 'hive' を指定して外部表を作成します。ファイル URI にはルートディレクトリ以下の全ファイルをワイルドカードで指定します。
DECLARE
l_TABLE_NAME DBMS_QUOTED_ID := '"CUSTSALES"';
l_CREDENTIAL_NAME DBMS_QUOTED_ID := '"OCI_CRED"';
l_FILE_URI_LIST CLOB :=
'https://objectstorage.<リージョン>.oraclecloud.com/n/<テナンシー名>/b/<バケット名>/o/custsales/*.parquet';
l_FORMAT CLOB :=
'{"schema":"first","type":"parquet","implicit_partition_type":"hive"}';
BEGIN
DBMS_CLOUD.CREATE_EXTERNAL_TABLE(
TABLE_NAME => l_TABLE_NAME,
CREDENTIAL_NAME => l_CREDENTIAL_NAME,
FILE_URI_LIST => l_FILE_URI_LIST,
FORMAT => l_FORMAT
);
END;
/
PL/SQLプロシージャが正常に完了しました。
l_FILE_URI_LIST の URI は実際の OCI Object Storage のパスに置き換え、クレデンシャル名(OCI_CRED)も事前準備で作成したものに合わせます。
"schema":"first" を指定すると、最初に見つかったファイルのスキーマを自動的に採用します。全ファイルのスキーマが統一されていることを確認してください。
Step 3: 作成された外部表の定義を確認
テーブルが正しく作成されたか、パーティション列が追加されているかを確認します。
-- テーブル定義の確認
SELECT column_name, data_type
FROM user_tab_columns
WHERE table_name = 'CUSTSALES'
ORDER BY column_id;
COLUMN_NAME DATA_TYPE
---------------- -------------
DAY_ID VARCHAR2
GENRE_ID NUMBER
MOVIE_ID NUMBER
CUST_ID NUMBER
APP VARCHAR2
DEVICE VARCHAR2
OS VARCHAR2
PAYMENT_METHOD VARCHAR2
LIST_PRICE BINARY_DOUBLE
DISCOUNT_TYPE VARCHAR2
DISCOUNT_PERCENT BINARY_DOUBLE
ACTUAL_PRICE BINARY_DOUBLE
COUNTRY VARCHAR2
MONTH VARCHAR2
YEAR VARCHAR2
Object Storage上のファイにはない、COUNTRY、YEAR、MONTH 列(VARCHAR2)が追加され、Hive スタイルのディレクトリ構造が正しく認識されていることが確認できます。
COLUMN_NAME DATA_TYPE
---------------- -------------
DAY_ID VARCHAR2
GENRE_ID NUMBER
...(Parquetファイル内の列)...
COUNTRY VARCHAR2 ← ディレクトリ構造から自動追加
YEAR VARCHAR2 ← ディレクトリ構造から自動追加
MONTH VARCHAR2 ← ディレクトリ構造から自動追加
補足: Implicit Partitioning はパーティション構造をデータベース・ディクショナリに保存しません。そのため
VIRTUAL_COLUMN = 'YES'にはならず、通常の VARCHAR2 列として表示されます。これはランタイムで検出される設計によるものであり、正常な動作です。
Step 4: 暗黙パーティションを使ったクエリ実行
仮想列をフィルタ条件に使い、パーティション・プルーニングが機能しているか確認します。
-- 特定の国・年・月のデータのみを取得
SELECT *
FROM CUSTSALES
WHERE COUNTRY = 'US'
AND YEAR = '2024'
AND MONTH = '01';
DAY_ID GENRE_ID MOVIE_ID CUST_ID APP DEVICE OS PAYMENT_METHOD LIST_PRICE DISCOUNT_TYPE DISCOUNT_PERCENT ACTUAL_PRICE COUNTRY MONTH YEAR
---------- -------- -------- ------- ------ ---------- ------- -------------- ---------- ------------- ---------------- ------------ ------- ----- ----
2024-01-12 4 1693 862120 MOBILE SMART_TV iOS GIFT_CARD 19.7 NONE 2.3 13.84 US 01 2024
2024-01-12 5 3621 132653 WEB SMART_TV Windows CREDIT_CARD 6.01 LOYALTY 11.0 9.51 US 01 2024
2024-01-19 1 3513 812048 MOBILE TABLET iOS PAYPAL 16.45 LOYALTY 4.1 9.24 US 01 2024
COUNTRY、YEAR、MONTH は Hive ディレクトリ名から抽出された文字列型の仮想列です。数値型の比較(YEAR = 2024 など)ではなく、文字列として比較(YEAR = '2024')します。
Step 5: クエリ実行計画でパーティション・プルーニングを確認
フィルタ条件を指定することで、Autonomous AI Database は country=US/year=2024/month=01/ ディレクトリのファイルのみを読み取り、他のディレクトリをスキップします。
EXPLAIN PLAN を使って、プルーニングが実際に機能していることを確認します。
EXPLAIN PLAN FOR
SELECT *
FROM CUSTSALES
WHERE COUNTRY = 'US'
AND YEAR = '2024'
AND MONTH = '01';
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2702861300
--------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 50 | 4650 | 519 (0)| 00:00:01 | | | |
| 1 | PX COORDINATOR | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10000 | 50 | 4650 | 519 (0)| 00:00:01 | Q1,00 | P->S | QC (RAND) |
| 3 | PX BLOCK ITERATOR | | 50 | 4650 | 519 (0)| 00:00:01 | Q1,00 | PCWC | |
|* 4 | EXTERNAL TABLE ACCESS STORAGE FULL| CUSTSALES | 50 | 4650 | 519 (0)| 00:00:01 | Q1,00 | PCWP | |
--------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - storage("COUNTRY"='US' AND "MONTH"='01' AND "YEAR"='2024')
filter("COUNTRY"='US' AND "MONTH"='01' AND "YEAR"='2024')
Note
-----
- automatic DOP: Computed Degree of Parallelism is 3 because of degree limit
実行計画の Predicate Information に以下のような storage(...) の行が出力されていれば、パーティション・プルーニングが正常に機能しています。
4 - storage("COUNTRY"='US' AND "MONTH"='01' AND "YEAR"='2024')
filter("COUNTRY"='US' AND "MONTH"='01' AND "YEAR"='2024')
Step 6: オブジェクト・ストレージのデータ変更に自動対応することを確認
暗黙パーティションの最大の特徴は、オブジェクト・ストレージ側の変更に自動対応することです。新しいディレクトリやファイルを追加した後、外部表の再作成や同期操作なしにそのままクエリを実行できます。
新しいデータ(例: month=04)をオブジェクト・ストレージに追加
OCI Object Storage に新しいフォルダを追加し、該当のファイルをアップロード
その後、クエリを実行
-- 外部表の変更なしにそのままクエリ可能
SELECT *
FROM CUSTSALES
WHERE COUNTRY = 'US'
AND YEAR = '2024'
AND MONTH = '04';
SELECT * FROM CUSTSALES WHERE COUNTRY='US' and YEAR='2024' and MONTH = '04';
DAY_ID GENRE_ID MOVIE_ID CUST_ID APP DEVICE OS PAYMENT_METHOD LIST_PRICE DISCOUNT_TYPE DISCOUNT_PERCENT ACTUAL_PRICE COUNTRY MONTH YEAR
---------- -------- -------- ------- ------ ---------- ------- -------------- ---------- ------------- ---------------- ------------ ------- ----- ----
2024-04-13 4 4278 728557 WEB SMARTPHONE MacOS CREDIT_CARD 16.4 PROMO 21.9 12.02 US 04 2024
2024-04-23 5 2471 754227 MOBILE SMARTPHONE Android GIFT_CARD 14.2 NONE 23.8 16.4 US 04 2024
2024-04-27 4 4483 259673 MOBILE SMARTPHONE iOS CREDIT_CARD 19.2 LOYALTY 20.3 4.49 US 04 2024
2024-04-11 4 1698 382485 TV PC Android CREDIT_CARD 10.44 LOYALTY 2.4 11.82 US 04 2024
Step 7: クリーンアップ(作成した外部表の削除)
検証が完了したら、作成した外部表を削除します。
-- 外部表の削除
DROP TABLE CUSTSALES;
DROP TABLE を実行してもオブジェクト・ストレージ上の実データファイルは削除されません。外部表の定義のみが削除されます。
おわりに
今回の検証では以下のことが確認できました。
-
implicit_partition_typeパラメータに'hive'を指定するだけで、Hive スタイルのフォルダ階層が自動的に仮想列として認識される - 仮想列を WHERE 句のフィルタ条件に指定することで、不要なディレクトリ・ファイルのスキャンを自動的にスキップするパーティション・プルーニングが機能する
- オブジェクト・ストレージ側のディレクトリやファイルを追加・変更しても、外部表の再定義や同期操作が不要で、即座にクエリで参照できる
- 外部表でありながらパーティション管理コストをゼロに近づけられるため、データレイクの運用負荷が大幅に軽減される
大量のファイルを階層的に管理するデータレイクを持つ組織、特に日次・月次でデータが増え続けるような運用環境において非常に有効です。
