カラムストアFAQ
OceanBaseの「カラムストア」とは?
OceanBaseのカラムストア(カラムストア)は、ディスク上の静的データをカラムナフォーマット(列形式)で保存し、メモリ上の変更データをローベース(行形式)で保存するデータストレージ形式です。これにより、スキャン性能とトランザクション処理能力の両立を図っています。
分析系のクエリにおいて、カラムストアはクエリ性能を大幅に向上させることができ、OceanBaseがHTAP(Hybrid Transactional/Analytical Processing)を実現する上で不可欠な機能です。従来の分析(AP)データベースでは、カラムストアデータは通常静的で、その場での更新が困難でした。OceanBaseのLSM-Treeアーキテクチャでは、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句を使用する目的は、インデックスキー以外の列データをインデックス内に格納することです。これにより、特定のクエリのパフォーマンスを最適化できます。テーブル本体へのアクセス(テーブルスキャン)を回避できるだけでなく、インデックスソートのコストも削減できます。さらに、クエリがインデックスに格納された列へのアクセスだけで完結する場合、クエリの効率を大幅に向上させることができます。
カラムストアテーブルとカラムストアのレプリカの違いは何ですか?
カラムストアのテーブルでは、テーブルのパーティションにおけるリーダーレプリカ(leader)とフォロワーレプリカ(follower)のスキーマが両方ともカラムストア形式であり、この場合、OLAPクエリは強い整合性読み取り(STRONGレベル)が可能です。一方、カラムストアレプリカは、テーブルのパーティションのリーダーレプリカ(leader)とフォロワーレプリカのスキーマが行ストア形式であることを前提とし、読み取り専用レプリカのリーダーのみがカラムストア形式となります。この場合、OLAPクエリは常に弱い整合性読み取り(WEAKレベル)となります。
カラムストアテーブルを作成するにはどうすればよいですか?
まず、行ストア・カラムストア混在テーブルを作成します。
- 非パーティションテーブル:
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つのベースラインデータを格納します。ただし、各テーブルはベースラインデータのコピーがいくつあっても、memtableやダンプ内の増分データは同一のものを共有します。
次に、純粋なカラムストアテーブルを作成します。
- 非パーティションテーブル:
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";
同様に、デフォルトのテーブル作成を行ストア、または行ストアとカラムストアの両方を保持するように設定することもできます。
alter system set default_table_store_format = "row"; //行ストア
alter system set default_table_store_format = "compound"; //行ストアとカラムストアの両方のデータ
カラムストア版の推奨設定
# 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列の文字数を増減させることもサポートしています。
カラムストアは様々なOffline 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);を実行した後、データを格納するグループがなくなる心配はありません。すべての列はDEFAUTL COLUMN GROUPという名前のデフォルトGroupに配置されます。
カラムストア内で複数の列をまとめてグループ化することはできますか?
OceanBaseデータベースV4.3.0では、各列を独立して保存するか、すべての列を行としてまとめて保存するかのいずれかのみをサポートしています。任意の複数の列を選択してまとめて保存することは、現時点ではサポートされていません。
カラムストアは更新をサポートしていますか?また、MemTable内の構造はどうなっていますか?
OceanBaseデータベースでは、追加、削除、変更の操作はすべてメモリ内で完了し、データは行ストア形式でMemTableに保存されます。一方、ベースラインデータは読み取り専用で、カラムストア形式でディスク上に保存されます。ある列のデータを読み取る際、MemTable内の行ストアデータとディスク上のカラムストアデータがリアルタイムで融合され、ユーザーに出力されます。これは、OceanBaseデータベースが、データの遅延なく、強整合性でカラムストアを読み取れることを意味します。MemTableに書き込まれたデータはダンプ(ディスクへの書き込み)をサポートしており、ダンプされたデータも引き続き行ストア形式で保存されます。マージが行われると、行ストアデータとベースラインのカラムストアデータが融合し、新しいベースラインのカラムストアデータが形成されます。
注意
カラムストアテーブルに対して大量の更新操作があり、タイムリーにマージが行われない場合、クエリのパフォーマンスに影響が出ます。したがって、最適なクエリ性能を得るためには、データの一括インポート後に一度マージ操作を開始することを推奨します。なお、少量の更新操作はパフォーマンスへの影響は軽微です。
カラムストアテーブルのクエリにはどのような特徴がありますか?
行ストアが冗長化されているテーブルでは、クエリロジックはデフォルトでrange scanの場合はカラムストアモードを使用し、point getの場合は行ストアモードにフォールバックします。
純粋なカラムストアテーブルでは、すべてのクエリがカラムストアモードを使用します。
カラムストアの特定の列にインデックスを作成することはサポートされていますか?
はい、サポートされています。OceanBaseデータベースは、カラムストアにインデックスを作成するか、行ストアにインデックスを作成するかを区別せず、作成されるインデックスの構造は同じです。
カラムストアの特定の1つまたは複数の列にインデックスを作成する意義は、カバリングインデックス(covering index)を構築してポイントルックアップクエリの性能を向上させたり、特定の列でソートすることでソート性能を向上させたりすることにあります。
最大で何列までサポートしていますか?
現在、1つのカラムストアテーブルで最大4096列までサポートしています。
カラムストアを使用する上での注意事項は何ですか?
第一に:データの一括インポート後、一度マージを行うことを推奨します。これにより、読み取り性能がさらに向上します。データインポート後、テナント内でalter system major freeze;を実行してマージをトリガーし、その後システムテナントでselect STATUS from CDB_OB_MAJOR_COMPACTION where TENANT_ID = {テナントID};を実行してマージが完了したかを確認します。STATUSがIDLEになればマージ完了です。
第二に:マージ後、統計情報の収集を推奨します。統計情報の収集方法は以下の通りです。
業務テナントで、すべてのテーブルに対して一度に統計情報を収集し、16スレッドで並列収集を開始します。
CALL DBMS_STATS.GATHER_SCHEMA_STATS ('db', granularity=>'auto', degree=>16);統計情報の収集の進捗は、ビュー
GV$OB_OPT_STAT_GATHER_MONITORで確認できます。
第三に:フルダイレクトロードロジックを使用してデータを一括インポートできます。この方法でデータをインポートしたテーブルは、マージを行わなくても最適なカラムストアのスキャン性能を発揮します。フルダイレクトロードをサポートするツールには、obloaderやネイティブのload dataコマンドがあります。
第四に::超ワイドテーブルではない場合、カラムストアを使用しなくてもカラムストアと同等の性能が得られることがあります。これはOceanBaseの行ストアバージョンにおける、マイクロブロックレベルの行列混合ストレージアーキテクチャによるものです。
第五に:データ量が大きいテーブルでは、コールドランとホットランで性能に差が出ます。
第六に:オプティマイザはコスト見積もりに基づき、列データへのアクセスに行ストアを使用するかカラムストアを使用するかを自動的に選択します。
第七に:カラムストアテーブルのマージ速度は遅くなります。
カラムストアテーブルのログ同期、バックアップ、リカバリなどに特別な点はありますか?
特別な点は何もありません。行ストアテーブルと同様です。同期されるログはすべて行ストアモードです。
データインポート/移行FAQ
ダイレクトロード(bypass import)とは何ですか?どのように行いますか?
ダイレクトロードは、データインポートを高速化し、クエリも高速化できるデータインポート方式です。大規模テーブルのデータインポートには、ダイレクトロード方式の使用を推奨します。現在、load dataコマンド、insert into select文がダイレクトロードをサポートしています。詳細な使用方法については、ダイレクトロードの概要を参照してください。
FlinkCDCを使用して他のデータベースからOceanBaseへデータを同期することはサポートされていますか?
はい、サポートしています。
Flink ConnectorからOceanBaseへのアクセスはサポートされていますか?
はい、サポートしています。詳細はhttps://github.com/oceanbase/flink-connector-oceanbaseを参照してください。
パフォーマンスチューニングFAQ
APクエリのパフォーマンスをさらに向上させる方法は他にありますか?
いくつかの実践的な経験から、まず特別なソート要件がない場合は、テーブル作成時に文字セットとして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を増やすことで、ダイレクトロードを高速化できます。
カラムストア向けのオプティマイザには、どのような特徴がありますか?
カラムストア向けのオプティマイザは、行ストア向けのオプティマイザと比較して、以下の点が追加されています。
- オプティマイザによる行ストア・カラムストアの自律的な選択能力。
- ヒントによる行ストア・カラムストアの選択制御能力(テーブルレベル)。
- カラムストアに適合した実行計画のコスト計算。
- カラムストアの遅延マテリアライゼーション(late materialization)の最適化の追加。