カラムストア FAQ
カラムストアとは?
OceanBaseのカラムストアは、ディスク上の静的データをカラムストア形式で保存し、メモリ上で変更されたデータを行ストア形式で保存するデータ格納形態です。これにより、スキャン性能とトランザクション処理能力の両方を兼ね備えています。
分析クエリにおいて、カラムストアはクエリ性能を大幅に向上させることができ、OceanBaseがHTAPを効果的に実現するために欠かせない機能です。従来のAPデータベースでは、カラムストアデータは通常静的であり、原位置での更新が困難です。一方、OceanBaseのLSMツリー構造では、SSTableは静的であり、カラムストアの実装に適しています。MemTableは動的であり、依然として行ストア形式であるため、トランザクション処理に追加の影響を与えません。これにより、TP型とAP型のクエリ性能をある程度両立させることが可能です。
「カラムストアインデックス」とは?
OceanBaseデータベースは、「カラムストアに対するインデックス作成」とは異なる、カラムストアインデックスの概念もサポートしています。カラムストアインデックスとは、インデックステーブルの構造がカラムストア形式であることを指します。
例えば、既に行ストアテーブル t6 があり、c3 の合計を求めたい場合、c3 に対してカラムストアインデックスを作成できます:
create table t6(
c1 TINYINT,
c2 SMALLINT,
c3 MEDIUMINT
);
create /*+ parallel(2) */ index idx1 on t6(c3) with column group (each column);
その他にも、より多くのインデックス作成方法をサポートしています:
インデックス内で冗長な行ストアをサポートします。
create index idx1 on t1(c2) storing(c1) with column group(all columns, each column); alter table t1 add index idx1 (c2) storing(c1) with column group(all columns, each column);インデックス内で純粋なカラムストアをサポートします。
create index idx1 on t1(c2) storing(c1) with column group(each column); alter table t1 add index idx1 (c2) storing(c1) with column group(each column);
データベースインデックスで STORING 句を使用する目的は、インデックスに追加の非インデックス列データを格納することです。これにより、特定のクエリの性能を最適化し、テーブルへの再アクセスを回避したり、インデックスソートのコストを削減したりできます。クエリがインデックスに格納された列にのみアクセスし、元の行をテーブルから取得する必要がない場合、クエリ効率を大幅に向上させることができます。
カラムストアテーブルとカラムストアレプリカのよくある質問
以下では、「カラムストアレプリカ」をCレプリカと統一して呼びます。
カラムストアテーブルとカラムストアレプリカの違いは何ですか? それらの関係はどうなっていますか?
両者は異なる観点から説明されています:
カラムストアテーブル:テーブルレベルの格納形態(行ストア、純粋なカラムストア、行列混合ストアなど)を指し、
WITH COLUMN GROUPまたはテナントレベルのdefault_table_store_formatなどによって決定されます。データは物理的にテナントの F(フル機能)/R(読み取り専用)レプリカ に保存されます。これらのレプリカ上では、MemTable/ダンプは引き続き行単位で組織され、ベースラインはカラムストアまたは行列冗長で組織されることがあります。読み取りパスは増分データとベースラインデータを統合します。F/R上で意味に合致するパスを実行する場合、デフォルトではレプリカのロールに応じた強整合性読み取り(トランザクションや分離レベルなどに依存)が得られます。カラムストアレプリカ(Cレプリカ):独立したレプリカタイプを指し、通常は独立したZoneに配置されます。Paxosの選挙や投票には参加せず、ログの非同期追従によってF/Rとの同期を図ります。ローカルの major層は主にカラムストア形式 でユーザーテーブルデータを負荷します。同一の論理テーブルは、F/R上では一つの格納形態(例えば行ストアや行列混合ストア)であり、Cレプリカ上ではカラムストア形態 となり、APとTPの リソース分離 に利用されます。
関係:両者は独立しています。Cレプリカがない テナント上にカラムストアテーブルを作成することも可能です(データはF/Rのカラムストアまたは混合形態のみに存在します)。また、Cレプリカを持つテナント内では、F/R上に行ストアテーブルを、Cレプリカ上に同一テーブルのカラムストア形態を 用意し、読み取り専用の分析を提供することもできます。カラムストアテーブルとCレプリカは同時に存在し、アーキテクチャ要件に応じて組み合わせることも可能です。
- 読み取りの整合性:Cレプリカはログソースに対して追従の遅延が生じます。独立したODPなどの方法でアクセスする分析クエリは、通常 弱い整合性読み取り として扱われます。TPと完全に同一のログ、Cレプリカの遅延なし を要求する場合、分析は優先的に F/R上のカラムストアテーブルまたは行列混合テーブル で完了させることが望ましいです。
カラムストアテーブル を作成するには、必ずしもカラムストアレプリカが必要ですか? Fullレプリカ上にカラムストアテーブルを作成できますか?
カラムストアレプリカは不要であり、Full(F)レプリカ上にカラムストアテーブルを作成することも可能です。
カラムストアテーブルはテーブルレベルのストレージ形式設定であり、テーブル作成時の WITH COLUMN GROUP またはテナントレベルの構成パラメータ default_table_store_format で指定します。テナントにF/Rレプリカがあればよいのです。任意のローカリティ(例えば F@zone1, F@zone2 のみ)で、カラムストアテーブルや行列混合テーブルを作成でき、データはF/Rレプリカ上にカラムストア(または行列冗長)形式で保存されます。カラムストアレプリカ(Cレプリカ)はオプションの独立したデプロイメント形態であり、TP/APの物理的または論理的分離および読み取り専用分析トラフィックに使用されます。「カラムストアテーブルを作成できるかどうか」とは依存関係がありません。
OceanBaseは直接に純粋なカラムストアテーブルを作成することをサポートしていますか? 行ストアテーブルに基づいて作成する必要がありますか?
純粋なカラムストアテーブルを直接作成できます。行ストアテーブルに基づく必要はありません。
テーブル作成時に WITH COLUMN GROUP (each column) を指定すると、純粋なカラムストアテーブルが作成されます(行ストアベースラインなし、カラムストアベースラインのみ)。例:
CREATE TABLE t (pk INT PRIMARY KEY, c1 INT, c2 INT) WITH COLUMN GROUP (each column);
パーティションテーブルでは、主キー列については、ポイントルックアップクエリのために行ストアが追加で保持されますが、全体としては純粋なカラムストアテーブルと見なされます。また、行ストアテーブルを作成した後、ALTER TABLE ... ADD COLUMN GROUP (each column); などのDDLを使用してカラムストアテーブルに変換することもできます。詳細については、本文の「カラムストアテーブルを作成する方法」を参照してください。
カラムストアと行ストア間のデータ一貫性はどのように保証されますか?非同期の場合、遅延はどの程度ですか?
2つのシナリオがあります:
- カラムストアテーブル(F/Rレプリカ上):ベースラインはカラムストアまたは行列混合レイアウトで、増分は行組織(MemTable/ダンプ)です。読み取り時に増分とベースラインを統合し、F/Rのデフォルトセマンティクスでは強整合性があり、レプリカ間の追加的な遅延はありません。
- カラムストアレプリカ(Cレプリカ):CレプリカはPaxosに参加せず、非同期ログを使用してF/Rを追従し、再生します。データはログソースに対して遅延があります。独立したODPからアクセスする場合、Cレプリカに対する分析読み取りは主に弱整合性で計画されます。TPと完全に同じログ、Cレプリカの遅延なしを要求する場合、分析は引き続きF/R上のカラムストアテーブルまたは行列混合テーブルで優先的に実行することをお勧めします。
TPとAPのトラフィックを分離する方法は何ですか?APに障害が発生した場合、災害復旧策はありますか?
トラフィック分離:
- Cレプリカなし:TPとAPは同じF/Rレプリカとアクセスエントリを共有し、オプティマイザーが自動的に行ストア/カラムストアのパスを選択します。TP/APのキャビネットやリンクレベルでの物理的隔離は行いません。
- Cレプリカあり:一般的な方法は、TPがF/Rへのアクセスエントリ(強読み取り/書き込み)を経由し、APが独立したODPを経由することです。ODP側で弱読み取りを設定し、リクエストをCレプリカにルーティングします(例:
proxy_primary_zone_name、route_target_replica_type = 'ColumnStore'、init_sql='set @@ob_route_policy = COLUMN_STORE_ONLY'など)。これにより、TP/APとCレプリカのリンク隔離が実現されます。運用保守とレプリカ管理については、カラムストアレプリカのデプロイと使用を参照してください。
AP(Cレプリカ)側の災害復旧と制限:
- Cレプリカはリーダーに復元できません。物理復元はCレプリカの復元をサポートしません(テナントのローカリティにCレプリカが含まれる場合、復元は失敗します)。メインデータベースにCレプリカがデプロイされていない場合、スタンバイデータベースにもCレプリカのデプロイは推奨されません。
- Cレプリカが配置されているゾーンまたはODPに障害が発生した場合、APのクエリはF/Rレプリカにフォールバックできます:APクライアントをメインODPへの接続に変更するか、ルーティングを調整して、分析リクエストをF/R上で強読み取りで実行します(TPとリソースを共有します)。
- V4.3.5 BP1から複数のCレプリカのデプロイがサポートされています(最大3個を推奨)。複数のゾーンにCレプリカをデプロイし、複数の独立したODPとルーティング設定を使用してAPの読み取り負荷を分散し、冗長性と高可用性を実現できます。
カラムストアレプリカのアクセスとルーティングFAQ
Cレプリカにアクセスする際、なぜ通常は独立したODPが必要なのですか?
OceanBase V4.3.5 では、APトラフィックをTPリンクから分離し、Cレプリカに安定してルーティングする一般的な方法は、Cレプリカのために別途ODPをデプロイすることです。そのODP上で弱読み取りとカラムストアルーティングポリシーを設定します。詳細な手順については、カラムストアレプリカのデプロイと使用を参照してください。
独立したODPはどこにデプロイすべきですか?専用サーバーの使用は必須ですか?
必須ではありません。独立したODPは、クラスタネットワークと相互接続可能な任意のホストにデプロイできます。ドキュメントで単一マシンデプロイを推奨する主な理由は、OBServerとのリソース競合リスクを低減するためであり、プロトコルや製品の制限ではありません。
proxy_idc_nameとカラムストアレプリカのルーティングはどのような関係ですか?
proxy_idc_nameは主にデータセンター親和性(LDC)ルーティングに使用されます。Cレプリカへのルーティングは、レプリカ選択の次元に属します。両者は同時に使用できますが、別々に設定と検証を行う必要があります。
詳細については、ODPの読み書き分離とルーティングポリシー、LDCルーティングを参照してください。
カラムストアテーブルを作成する方法は何ですか?
まず、行列混合テーブルを作成します。
- 非パーティションテーブル:
create table t1(
c1 TINYINT,
c2 SMALLINT,
c3 MEDIUMINT
) with column group (all columns, each column);
- パーティションテーブル:
create table t2(
pk int,
c1 int,
c2 int,
primary key (pk)
)
partition by hash(pk) partitions 4
with column group (all columns, each column);
行列混合のカラムストアテーブルを作成する際には、常に with column group (all columns, each column) 構文が使用されます。その意味は以下のとおりです:
all columns:すべての列をグループ化して1つのワイドカラムとし、行ごとに格納します。これは元の行ストアと一致します。each column:テーブル内の各列を個別にカラム形式で格納します。
all columns と each column が同時に現れる場合、デフォルトではカラムストアテーブル作成後も行ストアが冗長的に存在し、各レプリカが2つのベースラインデータを格納します。ただし、各テーブルのベースラインデータの数に関係なく、メモリテーブルやダンプにおける増分データは依然として同一のものを共有します。
次に、純粋なカラムストアテーブルを作成します。
- 非パーティションテーブル:
create table t3(
c1 TINYINT,
c2 SMALLINT,
c3 MEDIUMINT
) with column group (each column);
- パーティションテーブル:
create table t4(
pk1 int,
pk2 int,
c1 int,
c2 int,
primary key (pk1, pk2)
)
partition by hash(pk1) partitions 4
with column group (each column);
t4 テーブルの場合、pk1、pk2、c1、c2 に対してそれぞれカラムストアを作成し、(pk1, pk2) の組み合わせに対して行ストアも作成します。
テナントが作成するテーブルをデフォルトでカラムストアテーブルに設定するにはどうすればよいですか?
テナントレベルの構成パラメータを設定するだけです:
alter system set default_table_store_format = "column";
同様に、デフォルトのテーブル作成形式を行ストア、または行ストアとカラムストアの2重形式に設定することもできます:
alter system set default_table_store_format = "row"; // 行ストア
alter system set default_table_store_format = "compound"; // 行ストアとカラムストアの2重データ
カラムストア版の推奨設定は何ですか?
# collationをutf8mb4_binに設定すると、パフォーマンスが瞬時に15%向上します。
set global collation_connection = utf8mb4_bin;
set global collation_server = utf8mb4_bin;
set global ob_query_timeout= 10000000000;
set global ob_trx_timeout= 100000000000;
set global ob_sql_work_area_percentage=30;
set global max_allowed_packet=67108864;
# CPUコア数の10倍を推奨します。
set global parallel_servers_target=1000;
set global parallel_degree_policy = auto;
set global parallel_min_scan_time_threshold = 10;
# parallel_degree_policy = autoの場合の最大DOPを制限します。
# 大きなDOPが発生するとパフォーマンスに影響を与える可能性があります。以下の値はCPU_count * 2に設定することを推奨します。
set global parallel_degree_limit = 0;
alter system set compaction_low_thread_score = cpu_count;
alter system set compaction_mid_thread_score = cpu_count;
alter system set default_table_store_format = "column";
説明
上記のコードでは、cpu_countはテナント作成時に指定したmin_cpuを表します。
カラムストアに移行したかどうかの判断方法は何ですか?
スキャンがカラムストアモードで実行されている場合、EXPLAINにはTABLE FULL SCANが表示されます。カラムストアモードに移行した場合はCOLUMN TABLE FULL SCANが表示されます。以下のt5テーブルへのアクセスを例にします:
create table t5(
c1 TINYINT,
c2 SMALLINT,
c3 MEDIUMINT,
c4 INT,
c5 INT,
PRIMARY KEY(c1, c2)
) with column group(all columns, each column);
OceanBase(admin@test)>explain select c1,c2 from t5;
+------------------------------------------------------------------------+
| Query Plan |
+------------------------------------------------------------------------+
| =============================================== |
| |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| |
| ----------------------------------------------- |
| |0 |TABLE FULL SCAN|t5 |1 |3 | |
| =============================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([t5.c1], [t5.c2]), filter(nil), rowset=16 |
| access([t5.c1], [t5.c2]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([t5.c1], [t5.c2]), range(MIN,MIN ; MAX,MAX)always true |
+------------------------------------------------------------------------+
11 rows in set (0.011 sec)
OceanBase(admin@test)>explain select c1 from t5;
+------------------------------------------------------------------------+
| Query Plan |
+------------------------------------------------------------------------+
| ====================================================== |
| |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| |
| ------------------------------------------------------ |
| |0 |COLUMN TABLE FULL SCAN|t5 |1 |3 | |
| ====================================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([t5.c1]), filter(nil), rowset=16 |
| access([t5.c1]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([t5.c1], [t5.c2]), range(MIN,MIN ; MAX,MAX)always true |
+------------------------------------------------------------------------+
11 rows in set (0.003 sec)
カラムストアテーブルでの列の追加・削除は可能ですか?
列の追加と削除は可能です。
Varchar型の列の文字数の増減はサポートされています。
カラムストアは、行ストアテーブルと同様に、さまざまなオフラインDDLをサポートしています。
カラムストアの変更に関する詳細は、テーブルの行ストアからカラムストアへの変換(MySQLモード)およびテーブルの行ストアからカラムストアへの変換(Oracleモード)を参照してください。
カラムストアテーブルのクエリにはどのような特徴がありますか?
複雑な行ストアテーブルでは、カラムストアテーブルのクエリロジックはデフォルトでRange Scanを使用してカラムストアモードで実行されますが、Point Getクエリは行ストアモードに戻ります。
純粋なカラムストアテーブルでは、すべてのクエリがカラムストアモードで実行されます。
カラムストアはトランザクションをサポートしますか?トランザクションのサイズに制限はありますか?
行ストアテーブルと同様に、トランザクションをサポートしており、トランザクションのサイズに制限はなく、高い一貫性を備えています。
カラムストアテーブルのログ同期、バックアップ・リカバリなどに特別な点はありますか?
特別な点はなく、行ストアテーブルと同一です。同期されるログはすべて行ストアモードです。
行ストアテーブルをDDLでカラムストアテーブルに変更できますか?
可能です。追加の列ストアや削除の行ストアによって実現します。関連する構文例は以下のとおりです:
create table t1( pk1 int, c2 int, primary key (pk1));
alter table t1 add column group(all columns, each column);
alter table t1 drop column group(all columns, each column);
alter table t1 add column group(each column);
alter table t1 drop column group(each column);
説明
alter table t1 drop column group(all columns, each column); を実行した後、データを格納するGroupがないことを心配する必要はありません。すべての列は DEFAULTL COLUMN GROUP というデフォルトのGroupに配置されます。
カラムストアでは複数の列をまとめて格納することはできますか?
OceanBaseデータベースV4.3.0バージョンでは、各列は独立して格納されるか、すべての列が行としてまとめて格納されるかのどちらか のみをサポートしています。現在、任意の数の列を選択してまとめて格納することはサポートされていません。
カラムストアは更新をサポートしますか?また、MemTable内の構造はどのようになっていますか?
OceanBaseデータベースでは、追加、削除、変更操作はすべてメモリ内で完了し、データは行ストア形式でMemTableに保存されます。一方、ベースラインデータは読み取り専用で、カラムストア形式でディスクに保存されます。1列のデータを読み取る際、MemTable内の行ストアデータとディスク上のカラムストアデータをリアルタイムで統合し、ユーザーに出力します。これにより、OceanBaseデータベースは強整合性の読み取りをサポートし、データ遅延は発生しません。MemTableに書き込まれたデータはダンプをサポートしており、ダンプデータも引き続き行ストア形式で保存されます。マージ後、行ストアデータとベースラインカラムストアデータが統合され、新しいベースラインカラムストアデータが形成されます。
注意
カラムストアテーブルにおいて、大量の更新操作が発生し、適時にマージが行われない場合、クエリのパフォーマンスに影響が出る可能性があります。そのため、データの一括インポート後に一度マージ操作を実行し、最適なクエリパフォーマンスを得ることを推奨します。少数の更新操作はパフォーマンスに大きな影響を与えません。
カラムストアテーブルのクエリにはどのような特徴がありますか?
冗長行ストアテーブルでは、カラムストアテーブルのクエリロジックはデフォルトでrange scanがカラムストアモードで実行され、point getは引き続き行ストアモードに戻ります。
純粋なカラムストアテーブルでは、すべてのクエリがカラムストアモードで実行されます。
カラムストアの特定の列にインデックスを作成することはできますか?
可能です。OceanBaseデータベースは、カラムストアにインデックスを作成する場合でも行ストアにインデックスを作成する場合でも、作成されるインデックス構造は同じです。
カラムストアの1列または数列にインデックスを作成する意義は、カバリングインデックスを構築してポイントクエリのパフォーマンスを向上させたり、特定の列をソートしてソートパフォーマンスを向上させたりすることができる点にあります。
最大で何列をサポートしますか?
現在、1つのカラムストアテーブルは最大4096列をサポートします。
カラムストアの使用にあたっての注意点は何ですか?
第一:データを一括インポートした後、メジャーコンパクションを実行することを推奨します。これにより、読み取り性能が向上します。データインポート後、テナント内でメジャーコンパクションを1回トリガーし、すべてのデータがベースラインに入ることを確認します。その後、テナント内で alter system major freeze; を実行し、システムテナントで select STATUS from CDB_OB_MAJOR_COMPACTION where TENANT_ID = テナントID; を実行して、メジャーコンパクションが完了したかどうかを判断します。STATUS が IDLE に変わったら、メジャーコンパクションが完了したことを意味します。
第二:メジャーコンパクション後、統計情報の収集を1回行うことを推奨します。統計情報の収集方法は以下のとおりです:
業務テナントでワンクリックですべてのテーブルの統計情報を収集し、16個のスレッドを起動して並行収集します:
CALL DBMS_STATS.GATHER_SCHEMA_STATS ('db', granularity=>'auto', degree=>16);統計情報の進捗状況は、ビュー
GV$OB_OPT_STAT_GATHER_MONITORで確認できます。
第三:フルダイレクトロードロジックを使用してデータを一括インポートできます。この方法でデータをインポートしたテーブルは、メジャーコンパクションを行わなくても最適なカラムストアスキャン性能を達成できます。フルダイレクトロードをサポートするツールには、obloaderやネイティブのload dataコマンドが含まれます。
第四:非ワイドテーブルの場合、カラムストアを使用しなくても、カラムストアと同等の性能を達成できる可能性があります。これは、OceanBaseの行ストアバージョンにおけるマイクロブロックレベルの行と列のハイブリッドストレージアーキテクチャのおかげです(このような場合には驚かないでください)。
第五:大規模データテーブルでは、cold runとhot runの性能に差があります。
第六:オプティマイザーはコスト評価に基づき、行ストアとカラムストアのどちらを使用してカラムデータにアクセスするかを自動的に選択します。
第七:カラムストアテーブルのメジャーコンパクション速度は遅くなります。
カラムストアテーブルのログ同期、バックアップ・リカバリなどに特別な点はありますか?
特に特別な点はなく、行ストアテーブルと同じです。同期されるログはすべて行ストアモードです。
データインポート/移行 FAQ
ダイレクトロードとは何ですか?ダイレクトロードの方法を教えてください。
ダイレクトロードは、データインポートを高速化し、データクエリも高速化できるデータインポート方式です。大規模なテーブルのデータインポートには、ダイレクトロード方式の使用を推奨します。現在、load data コマンドと insert into select ステートメントはダイレクトロードをサポートしています。ダイレクトロードの詳細な使用方法については、ダイレクトロードの概要を参照してください。
FlinkCDCを使用して他のデータベースからOceanBaseにデータを同期することは可能ですか?
可能です。公式ドキュメントMySQLからOceanBaseへのFlinkCDCを使用したデータ同期を参照してください。
Flink ConnectorでOceanBaseにアクセスすることは可能ですか?
可能です。詳細は https://github.com/oceanbase/flink-connector-oceanbase。 を参照してください。
パフォーマンスチューニング FAQ
AP Queryのパフォーマンスをさらに向上させる方法はありますか?
実践経験から得られた知見によると、まず特別なソート要件がない限り、テーブル作成時に文字セットとしてutf8mb4ではなくbinaryを使用することで、パフォーマンスが向上します。例:
create table t5(c1 TINYINT, c2 VARVHAR(50)) CHARSET=binary with column group (each column);
次に、ユーザーまたは業務上許容される場合、MySQLテナントでテーブル作成時にutf8mb4_bin文字セットを指定し、CHARSET = utf8mb4 collate=utf8mb4_binオプションを追加します。
さらに、UNITのIOPSを向上させることで、ダイレクトロードを高速化できます。
カラムストア向けオプティマイザーにはどのような特徴がありますか?
カラムストア向けオプティマイザーは、行ストア向けオプティマイザーと比較して、以下の点が追加されています:
- オプティマイザーが行と列のストアを自動選択する能力。
- 行と列のストア選択を制御するHint機能(テーブルレベル)。
- カラムストアに適応した計画コスト計算。
- カラムストアの遅延マテリアライゼーション最適化の追加。