TiDB Serverless : HTAP と TiFlash
過去何度か記事で触れたようにTiDBはオンライン向けOLTPトランザクションと分析向けOLAP両方をサポートするHTAPデータベースとして開発が継続されています。
地理的に離れた場所に、適材適所でOLTP型とOLAP型データベースを構築するアーキテクチャが
一般的だとおもいますが、TiDBがHTAPへの道を切り開き多くのデータベースが進化を
繰り広げています。
ビッグデータ解析のアーキテクチャもこれによりスタンダードがわかっていくかもしれません。
これはどのように実現しているのでしょうか。まずそれに触れる前に、列指向型の技術的特徴に触れます。
列指向型データ
話をシンプルにするために一旦データベースを忘れて単純なCSVファイルを想定します。
通常のCSVファイルは行指向型です。例えば以下のようなシンプルなデータを想定します。
3人の年齢の平均値を計算する場合、行指向型ではデータは1行ごとに読み込まれますから、以下のようにデータが読み込まれることになります。
1,Bob,20,2,Alice,42,3,Eve,37
この後(20+42+37)/3が計算されるわけです。つまり必要のないデータを6個読み込んでしまっているわけです。これをParquet等の列指向型にすると読み込まれるデータは以下です。
20,42,37
読み込むデータ量が少なくなるため、当然処理が高速化します。
保存されるデータはクラウドストレージの利用量などを節約するために圧縮されるケースが増えています。また昨今のクラウドを活用した分散ストレージアーキテクチャを採用したデータベースなどはデータのやり取りがネットワークを介して行われるため、圧縮化は必須技術になります。コンピュートパワーやストレージよりネットワークは、はるかに遅いためです。
この視点で先ほどのデータをもう一度見てみます。行指向の場合、
1,Bob,20,2,Alice,42,3,Eve,37
これは以下と言い換えることができます。
int,varchar,int,int,varchr,int,int,varcar,int
一方列指向型データフォーマットは以下です。
1,2,3,Bob,Alice,Eve,20,42,37
int,int,int,varchar,varchar,varchar,int,int,int
どちらの方が圧縮効率が高いかは言うまでもありません。このような理由から分析には一般的に列指向型が使われます。
TiDB と 列指向型ストレージ / TiFlash
TiDBのストレージは2種類あります。
TiKV : 行指向型ストレージ
TiFlash : 列指向型ストレージ
通常TiDB Clusterを起動するとそれがDedicated型であれ、Serverless型であれTiKVで起動されます。
この辺りは中の人のKoiPingさんの解説がわかりやすいです。
これに対して追加でTiFlashストレージをくっつけTiKVとレプリケーションを張ることが出来ます。
レプリケーションは非同期で行われユーザーは意識する必要がありません。また非同期ですからTiFlashのパフォーマンスはTiKVを用いて動作するOLTPアプリケーションには影響を与えません。
さっそくやってみる
では集計系のデータでTiKVとTiFlashのパフォーマンスの違いを見ていきます。
まずは以下のとてもシンプルなテーブルを作成します。
use test;
CREATE TABLE OLAPTEST (
ID int,
Age int,
PRIMARY KEY (ID)
);
次に1000件のダミーデータを入れます。
import random
with open('insert_olaptest.sql', 'w') as f:
f.write("INSERT INTO OLAPTEST (ID, Age) VALUES\n")
for i in range(1, 1001):
age = random.randint(0, 99) # 0から99の範囲でランダムに生成
if i == 1000:
f.write(f"({i}, {age});\n")
else:
f.write(f"({i}, {age}),\n")
実行して生成されたSQLファイルの中身をそのまま実行すれば1000件のデータが挿入されます。
Age
の平均値を取得すると以下になります。
select avg(Age) from test.OLAPTEST;
SQLの実行計画を出力すると以下のようになっており、TiKV
が使われていることがわかります。
desc select avg(Age) from test.OLAPTEST;
ではここからTiFlash ストレージを作成してTiKVからデータを非同期レプリケーションさせます。
ALTER TABLE test.`OLAPTEST` SET TIFLASH REPLICA 2;
TiDB Serverlessの場合、作成可能なStorageは2
で固定になります。
なお作成されたReplicaを削除する直接的なコマンドはなく、以下で削除が可能になります。
ALTER TABLE test.`OLAPTEST` SET TIFLASH REPLICA 0;
以下のコマンドでReplicaの作成状況を確認できます。
SELECT * FROM information_schema.tiflash_replica WHERE TABLE_NAME = 'OLAPTEST';
なおLOCATION_LABELS
ですが、ServerlessではないClusterでは意図的に異なるZoneやRegionを指定することでDR用TiFlashを作ることが可能のようです。
AVAILABLE
とProgress
の1
は若干わかりずらいのですが、これは100%
を意味しています
AVAILABLE
が1
ということは2つのReplicaが準備されたという意味です。同様にProgress
の1
はデータ同期が100%
行われている、という意味です。
以下のSQLを実行します。
use test;
set @@session.tidb_isolation_read_engines = "tiflash";
select avg(Age) from OLAPTEST;
tikv
とtiflash
の値を切り替えてパフォーマンスを見てください。今回はとてもシンプルなテーブルなのでそこまで大きい差は生まれませんが、ちゃんと差が出ていることがわかります。
実行計画を見ると対象がtiflash
になっていることがわかります。
desc select avg(Age) from OLAPTEST;
なお今回は意図的にset @@session.tidb_isolation_read_engines = "tiflash";
と利用するストレージを使用していますが、通常はオプティマイザが自動的にtikv
かtiflash
を指定してくれるため、明示的な指定は不要です。
set @@session.tidb_isolation_read_engines = "tiflash";
を用いた場合セッション単位で利用されるストレージが確定されるため、単一セッションのSQL単位で明示的に利用するストレージを切り替える場合、以下のようにSQLヒントでの指定も可能となっています。
select /*+ read_from_storage(tiflash[table_name]) */ ... from table_name;
もう少し詳しい情報を知りたい方はこちらを参考にしてください。
Discussion