CREATE TABLE ステートメントを使用して、テーブルを作成できます。
この記事では主に非パーティションテーブルの作成について説明します。パーティションテーブルの作成と使用方法については、パーティションテーブルの作成を参照してください。
パーティション化されていないテーブルの作成
パーティション化されていないテーブルとは、パーティションが1つしかないテーブルを指します。
パーティション化されていないテーブルを作成するためのサンプルステートメントは以下のとおりです:
obclient> CREATE TABLE table_name1(w_id int,
w_ytd decimal(12,2),
w_tax decimal(4,4),
w_name varchar(10),
w_street_1 varchar(20),
w_street_2 varchar(20),
w_city varchar(20),
w_state char(2),
w_zip char(9),
unique(w_name, w_city),
primary key(w_id)
);
obclient> CREATE TABLE table_name2 (c_w_id int NOT NULL,
c_d_id int NOT null,
c_id int NOT null,
c_discount decimal(4, 4),
c_credit char(2),
c_last varchar(16),
c_first varchar(16),
c_middle char(2),
c_balance decimal(12, 2),
c_ytd_payment decimal(12, 2),
c_payment_cnt int,
c_credit_lim decimal(12, 2),
c_street_1 varchar(20),
c_street_2 varchar(20),
c_city varchar(20),
c_state char(2),
c_zip char(9),
c_phone char(16),
c_since date,
c_delivery_cnt int,
c_data varchar(500),
FOREIGN KEY (c_w_id) REFERENCES table_name1(w_id),
primary key (c_w_id, c_d_id, c_id)
);
この例では、2つのテーブルを作成し、それぞれのテーブルの列に対して、主キーや外部キーなどの制約情報を定義しています。主キーや外部キーの詳細については、列の制約タイプの定義を参照してください。
テーブルの列を作成する際は、正しいデータ型を選択してください。SQLデータ型の詳細については、データ型を参照してください。
説明
パフォーマンスと今後のメンテナンスのニーズに基づき、テーブル作成時に主キーまたは一意キーを設計することを推奨します。適切なフィールドが主キーとして使用できない場合は、数値列を追加して主キーとし、Oracleテナントのシーケンスを使用してその列に値を埋め込むことができます。シーケンスの詳細については、シーケンスの管理を参照してください。
レプリケーションテーブルの作成
レプリケーションテーブルとは、OceanBaseデータベースにおける特殊なテーブルです。このテーブルは、任意の「正常」なレプリカから最新のデータ変更を読み取ることができます。書き込み頻度が低く、読み取り操作の遅延やロードバランシングの要件が高いユーザーにとって、レプリケーションテーブルは非常に適した選択肢です。
ユーザーがレプリケーションテーブルを作成すると、そのテナント内のすべてのOBServerノードにレプリケーションテーブルのレプリカが作成されます。これらのレプリカのうち1つがリーダーとして選ばれ、書き込みリクエストを受け付け、残りのレプリカは読み取りリクエストのみを受け付けることができます。
すべてのレプリカはリーダーに対して状態を報告する必要があり、主にレプリカの再生進捗、つまりデータ同期の進捗を報告します。一般的に、フォロワーの再生進捗はリーダーよりも若干遅れますが、その遅れが一定のしきい値を超えない限り、リーダーはレプリカを「正常」な状態と判断し、リーダー上の変更を迅速に再生できると見なします。リーダーが特定のレプリカを一定時間「正常」と判断した後、フォロワーに一定期間のリースを付与します。一般的に言えば、リーダーは今後一定期間、フォロワーが「正常」な状態を維持し、強い一貫性を持つ読み取りサービスを提供できると「信頼」します。この「信頼」期間中、リーダーは各レプリケーションテーブルトランザクションをコミットする前に、フォロワーの再生進捗を確認します。フォロワーがそのトランザクションの変更を再生した後、リーダーはユーザーに対してトランザクションのコミット成功を報告します。この時点で、ユーザーはフォロワー上で、直前にコミットされたトランザクションの変更を読み取ることができます。
レプリケーションテーブル機能は、OceanBaseデータベースV3.xバージョンからすでに存在しています。一方、V4.xバージョンでは、OceanBaseデータベースのアーキテクチャが大幅に変更されたため、V4.xのレプリケーションテーブルは、単一マシンログストリームの新しいアーキテクチャに適応するため、パーティションに基づく読み取り可能なバージョン番号検証と、ログストリームに基づくリース付与メカニズムを構築し、強い一貫性を持つ読み取りの正確性を保証しています。
また、V4.xバージョンのレプリケーションテーブル機能では、リーダー切り替え時にトランザクションをキルしない機能が強化されました。ユーザーまたはロードバランシングがリーダーの切り替えを開始した場合、未コミットのレプリケーションテーブルトランザクションは、V3.xバージョンのように継続できなくなることはなく、リーダー切り替え後も実行を続けることができます。V3.xバージョンと比較して、V4.xのレプリケーションテーブル機能は、書き込みトランザクションのパフォーマンスが向上し、災害復旧能力も強化されており、レプリカのダウンは読み取り操作への影響をより低くしています。
テーブル複製の使用制限
テーブル複製:
テーブル複製の作成制限:sysテナントおよびmetaテナントにはブロードキャストログストリームがないため、テーブル複製の作成はサポートされていません。
書き込み性能はノード数に影響を受けます:テーブル複製の書き込みではすべてのレプリカに同期する必要があるため、ノード数が多いほど書き込み性能への影響が大きくなります。
- 回避策:テーブル複製の書き込みと読み取りを同一トランザクションで行うことを避けることを推奨します。テーブル複製トランザクションの純粋な書き込みまたは読み取りは問題ありません。
プロパティ変換:
- テーブル複製とTableGroupは排他的であり、テーブル複製のTableGroupプロパティを変更しようとするとエラーが発生します。通常のテーブルをテーブル複製に変換する際、その通常のテーブルが特定のTableGroupに属している場合、プロパティ変更コマンドでエラーが報告されます。
- テーブル複製の変換はロードバランシングと転送に依存しており、関連する構成パラメータが有効になっていることを確認する必要があります。
ルーティング:
トランザクション内でテーブル複製の書き込み操作が行われ、その後テーブル複製を照会する場合、ランダムルーティングでフォロワーにルーティングされると、レプリカが読み取り不可能という問題が発生し、オブザーバー内部で再ルーティングが行われてテーブル複製のリーダーに転送されるため、照会性能に影響を与えます。
- ODP V4.3.3ではルーティング戦略が調整されており、テーブル複製の書き込み操作があった場合、その後の照会はテーブル複製のリーダーにルーティングされます。
テーブル複製と通常のテーブルの
JOINクエリ操作では、テーブル複製に基づいてランダムルーティングが行われます(JOINクエリについては、ODPは最初のテーブルに基づいてルーティングします)。この場合、通常のテーブルの非リーダーノードにルーティングされる可能性があり、リモート計画が発生する原因となります。通常のテーブルのプロパティをテーブル複製に変更しても、ODPはそれを検出できず、テーブル複製に基づいて負荷を分散するルーティングを行うことができません。
トランザクション内でテーブル複製に変更が加えられた後のクエリ操作:テーブル複製を照会する際、生成される実行計画はローカルレプリカを選択しますが、変更が加えられているため、レプリカが読み取り不可能というエラーが報告されます。SQLの再試行ではリーダーレプリカが選択されますが、この時点でプランキャッシュにヒットしないため、クエリ性能が低下します。
説明
OceanBaseデータベースV4.3.5では、V4.3.5 BP2以降のバージョンから、トランザクション内でテーブル複製に変更が加えられた場合、システムは照会時に常にテーブル複製のリーダーレプリカを優先的に選択し、ローカルレプリカを直接選択することはありません。これにより、OceanBaseデータベースのクエリ効率が向上し、誤ったレプリカの選択を回避できます。
ブロードキャストログストリーム:
- 各ユーザーテナントは最大1つのブロードキャストログストリームしか持てません。
- ブロードキャストログストリームと通常のログストリーム間のプロパティ変換はサポートされていません。
- ブロードキャストログストリームの手動削除はサポートされておらず、現在はテナントの削除に伴って自動的に削除されます。
レプリケーションテーブルの作成構文
レプリケーションテーブルを作成する構文は、CREATE TABLE ステートメントの後に DUPLICATE_SCOPE オプションを追加することです。ユーザーテナントのみがレプリケーションテーブルを作成でき、sys テナントではレプリケーションテーブルを作成できません。レプリケーションテーブルを作成するSQLステートメントは以下のとおりです:
CREATE TABLE table_name column_definition DUPLICATE_SCOPE='none | cluster';
ここで、DUPLICATE_SCOPE パラメータはレプリケーションテーブルの属性を指定するために使用され、値は以下のとおりです:
none:このテーブルが通常のテーブルであることを示します。cluster:このテーブルがレプリケーションテーブルであり、リーダーがトランザクションを現在のテナントのすべてのFコピーおよびRコピーに複製する必要があることを示します。
テーブル作成時に DUPLICATE_SCOPE を指定しない場合、デフォルト値は none です。
CREATE TABLE dup_t1 (c1 NUMBER,c2 NUMBER) DUPLICATE_SCOPE= 'cluster';
特定のテナントの最初のレプリケーションテーブルが作成されると、システムは同時に特別なログストリーム、つまりブロードキャストログストリームも作成します。その後に新規作成されるレプリケーションテーブルはすべてこのブロードキャストログストリーム上に作成されます。ブロードキャストログストリームと通常のログストリームとの違いは、ブロードキャストログストリームが自動的にテナント内の各OBServerノードにコピーをデプロイし、理想的な状況下ではレプリケーションテーブルが任意のOBServerノードで強い整合性読み取りを提供できることを保証する点です。以下のSQLを使用して、テナントのレプリケーションテーブルが属するブロードキャストログストリームを確認できます:
SELECT * FROM SYS.DBA_OB_LS WHERE flag LIKE "%DUPLICATE%";
クエリ結果の例は以下のとおりです。
+-------+--------+--------------+---------------+-------------+---------------------+----------+---------------------+---------------------+-----------+
| LS_ID | STATUS | PRIMARY_ZONE | UNIT_GROUP_ID | LS_GROUP_ID | CREATE_SCN | DROP_SCN | SYNC_SCN | READABLE_SCN | FLAG |
+-------+--------+--------------+---------------+-------------+---------------------+----------+---------------------+---------------------+-----------+
| 1003 | NORMAL | z1;z2 | 0 | 0 | 1684982852976428261 | NULL | 1684983282912048623 | 1684983282912048623 | DUPLICATE |
+-------+--------+--------------+---------------+-------------+---------------------+----------+---------------------+---------------------+-----------+
1 rows in set
例では、LS_ID が 1003 のログストリームがブロードキャストログストリームであり、現在のテナントのすべてのレプリケーションテーブルはこのログストリーム上に作成されています。ブロードキャストログストリームの詳細については、コピーの紹介を参照してください。
レプリケーションテーブルの作成が成功すると、通常のテーブルと同様に挿入や読み書き操作を行うことができます。ただし、読み取りリクエストについては、Proxy方式でデータベースに接続する場合、読み取りリクエストが任意のOBServerノードにルーティングされて実行される可能性があります。一方、直接接続方式でデータベースに接続する場合、ローカルコピーが読み取り可能であれば、システムは直接接続したOBServerノード上で読み取りリクエストを実行します。その他のデータベース接続方法の詳細については、接続方式の概要を参照してください。
既存のテーブルのデータをコピーして新しいテーブルを作成する
CREATE TABLE AS SELECT ステートメントを使用して、テーブルの基本データ型とデータをコピーしますが、制約、インデックス、NOT NULLなどのプロパティは含まれません。
サンプルステートメントは以下のとおりです:
CREATE TABLE t2_copy AS SELECT * FROM t2;
CREATE TABLE LIKE ステートメントを使用してテーブル構造をコピーすることはサポートされていません。
行ストアテーブルの作成
OceanBaseデータベースは、行ストアテーブルの作成および行ストアとカラムストアの変換機能をサポートしています。
構成パラメータdefault_table_store_format=‘row’(デフォルト値)が設定されている場合、デフォルトで作成されるテーブルは行ストアテーブルになります。default_table_store_formatがrow以外の場合は、WITH COLUMN GROUP(all columns)オプションを設定することで行ストアテーブルを作成できます。
行ストアとカラムストアの変換に関する詳細は、テーブルの変更を参照してください。カラムストアインデックスの作成に関する詳細は、インデックスの作成を参照してください。
WITH COLUMN GROUP(all columns)を指定して行ストアテーブルを作成します。
例:
CREATE TABLE tbl1_cg (col1 INT PRIMARY KEY, col2 VARCHAR(50)) WITH COLUMN GROUP(all columns);
説明
WITH COLUMN GROUP(all columns)オプションを使用して行ストアテーブルを作成した場合、ユーザーが後でこの列グループを削除するために DROP COLUMN GROUP(all columns) コマンドを実行しても、テーブルは引き続き行ストア形式を維持します。
カラムストアテーブルの作成
OceanBaseデータベースは、カラムストアテーブルの作成、行ストアからカラムストアへの変換、およびカラムストアインデックスの作成機能をサポートしています。WITH COLUMN GROUPオプションを設定することで、明示的にカラムストアまたは行ストアとカラムストアの冗長状態を指定できます。また、構成パラメータdefault_table_store_formatを設定することで、カラムストアまたは行ストアとカラムストアの冗長をデフォルトのストレージ形式に設定することもできます。
行ストアからカラムストアへの変換に関する詳細は、テーブルの変更を参照してください。カラムストアインデックスの作成に関する詳細は、インデックスの作成を参照してください。
WITH COLUMN GROUP(all columns, each column)を指定して、行ストアとカラムストアの冗長テーブルを作成します。
例:
CREATE TABLE tbl1_cg (col1 NUMBER PRIMARY KEY, col2 VARCHAR2(50)) WITH COLUMN GROUP(all columns, each column);
WITH COLUMN GROUP(each column)を指定して、カラムストアテーブルを作成します。
例:
CREATE TABLE tbl2_cg (col1 NUMBER PRIMARY KEY, col2 VARCHAR2(50)) WITH COLUMN GROUP(each column);
カラムストアテーブルを作成して使用する際、大量のデータをインポートした場合は、読み取り性能を向上させるために一度のコンパクション操作を実行し、統計情報収集を行い、実行戦略を調整する必要があります。
コンパクション操作:一括インポート後、一度のコンパクション操作を実行することを推奨します。これは、断片化されたデータを整理し、物理ストレージ上でより連続的にすることで、読み取り時のディスクI/Oを削減し、読み取り性能を向上させるのに役立ちます。データをインポートした後、テナント内で一度のコンパクション操作をトリガーして、すべてのデータがベースライン層にコンパクションされるようにします。操作については、
MAJOR AND MINORを参照してください。統計情報収集:コンパクション操作完了後、統計情報の収集を推奨します。これは、オプティマイザーが効果的なクエリ計画と実行戦略を生成するために非常に重要です。GATHER_SCHEMA_STATSを実行して、すべてのテーブルから統計情報を収集し、ビューGV$OB_OPT_STAT_GATHER_MONITORを使用して収集進捗を監視できます。
注意が必要な点として、カラムストアテーブルのデータ量が増加するにつれて、コンパクション操作の速度が低下する可能性があることです。
テーブルの更新モデルを指定する
テーブル作成時に更新モデルを指定する構文は、CREATE TABLE ステートメントの後にテーブルオプション MERGE_ENGINE を追加することです。SQLステートメントは以下のとおりです:
CREATE TABLE table_name column_definition
MERGE_ENGINE = {delete_insert | partial_update}
WITH COLUMN GROUP([all columns,] each column);
説明
- パラメータ
MERGE_ENGINEは、テーブル作成時に指定した後、その設定値は変更できません。 - OceanBaseデータベースV4.3.5では、V4.3.5 BP3バージョンから
MERGE_ENGINEパラメータがサポートされています。
ここで、MERGE_ENGINE パラメータはテーブルの更新モデルを指定するために使用され、値は以下のとおりです:
partial_update:デフォルト値であり、既存の更新モードを変更しないことを意味します。delete_insert:merge on write方式を採用し、updateをdeleteとinsertに変換し、かつフルカラム書き込みを行うことを意味します。
MERGE_ENGINE オプションを指定しない場合、このオプションの値は構成パラメータ default_table_merge_engine の値と同じになります。
適用シナリオ
OLAPシナリオでは delete_insert の使用を推奨しますが、それ以外のシナリオでは partial_update の使用を推奨します。その他の構成シナリオの詳細については、構成のベストプラクティス を参照してください。
例:
クリーンカラムストアテーブル
mer_tbl1を作成し、更新モデルはmerge on writeです。CREATE TABLE mer_tbl1 (col1 NUMBER, col2 NUMBER) MERGE_ENGINE = delete_insert WITH COLUMN GROUP(each column);ラインストアとカラムストアの冗長テーブル
mer_tbl2を作成し、更新モデルはmerge on writeです。CREATE TABLE mer_tbl2 (col1 NUMBER, col2 NUMBER) merge_engine = delete_insert WITH COLUMN GROUP(all columns, each column);
一時テーブルの作成
OceanBaseデータベースのOracleモードでは、一時テーブルはトランザクションまたはセッション期間中に存在するデータのみを保存します。
CREATE GLOBAL TEMPORARY TABLE ステートメントを使用してグローバル一時テーブルを作成できます。構文は以下のとおりです:
CREATE GLOBAL TEMPORARY TABLE table_name column_definition {ON COMMIT DELETE ROWS | ON COMMIT PRESERVE ROWS};
パラメータの説明は以下のとおりです:
ON COMMIT DELETE ROWS:トランザクションレベルの一時テーブル。コミット時にデータを削除します。ON COMMIT PRESERVE ROWS:セッションレベルの一時テーブル。セッション終了時にデータを削除します。
説明
グローバル一時テーブルにはインデックスを作成できますが、グローバル一時テーブルのインデックスデータも一時的であり、データはSession固有です。
例
例1:トランザクションレベルの一時テーブルを作成する
トランザクションレベルの一時テーブル
tbl1を作成します。obclient> CREATE GLOBAL TEMPORARY TABLE tbl1(col1 INT) ON COMMIT DELETE ROWS;テーブル一時テーブル
tbl1にデータを1件挿入します。obclient> INSERT INTO tbl1 VALUES(1);一時テーブル
tbl1のデータを照会します。obclient> SELECT * FROM tbl1;実行結果は次のとおりです:
+------+ | COL1 | +------+ | 1 | +------+ 1 row in setトランザクションをコミットします。
obclient> COMMIT;再度一時テーブル
tbl1のデータを照会します。obclient> SELECT * FROM tbl1;実行結果は次のとおりです:
Empty set
例2:セッションレベルの一時テーブルを作成する
セッション1で以下の操作を実行します:
セッションレベルの一時テーブル
tbl2を作成します。obclient> CREATE GLOBAL TEMPORARY TABLE tbl2(col1 INT) ON COMMIT PRESERVE ROWS;テーブル一時テーブル
tbl2にデータを1件挿入します。obclient> INSERT INTO tbl2 VALUES(1);一時テーブル
tbl2のデータを照会します。obclient> SELECT * FROM tbl2;実行結果は次のとおりです:
+------+ | COL1 | +------+ | 1 | +------+ 1 row in setトランザクションをコミットします。
obclient> COMMIT;再度一時テーブル
tbl2のデータを照会します。obclient> SELECT * FROM tbl2;実行結果は次のとおりです:
+------+ | COL1 | +------+ | 1 | +------+ 1 row in set
セッション2で、またはセッション1を終了して再接続した後に以下の操作を実行します:
一時テーブル tbl2 のデータを照会します。
obclient> SELECT * FROM tbl2;
実行結果は次のとおりです:
Empty set