🌟

Snowflake - Hybrid Table / Unistoreのパフォーマンスを検証してみた!

2022/08/30に公開

この記事は何

Snowflake Summit 2022にて発表された Hybrid Tableをデモ環境にて検証することが出来たので、検証内容とその結果をまとめました。

なお、Hybrid TableについてはPrivate Previewの機能となっており、今回の検証は記事公開時点(2022年8月30日)での検証内容であることにご留意ください。

Hybrid Tableとは

Hybrid Tableは、Snowflake上で作成できるOLTP向けテーブルのことで、これまでのOLAP向けテーブルとのシームレスな統合を実現することができます。
Snowflakeが提唱するUnistoreと呼ばれるOLTP/OLAPの統合ワークロードの核となる機能として提供されています。

手前味噌にはなりますが、より詳しい内容はこちらをご確認いただければと思います。

検証環境

検証に使うデータ

今回は、以下のようなデモデータを用いて検証を行います。

各テーブルのSQL定義は以下のようになります。Hybrid Tableの場合は、Primary Keyの設定が必須です。

create or replace hybrid table region_hybrid (
    r_regionkey number not null primary key,
    r_name string not null,
    r_comment string
);

create or replace hybrid table nation_hybrid (
    n_nationkey number not null primary key,
    n_name string not null,
    n_regionkey number not null,
    n_comment string not null,
    constraint fK_regionkey foreign key (n_regionkey) references region_hybrid(r_regionkey)
);

create or replace hybrid table customer_hybrid (
    c_custkey number not null primary key,
    c_name string not null,
    c_address string not null,
    c_nationkey number not null,
    c_phone string not null,
    c_acctbal number not null,
    c_mktsegment string,
    c_comment string,
    constraint fk_nationkey foreign key (c_nationkey) references nation_hybrid(n_nationkey)
);

create or replace hybrid table orders_hybrid (
    o_orderkey number not null primary key,
    o_custkey number not null,
    o_orderstatus string not null,
    o_totalprice number not null,
    o_orderdate date not null,
    o_orderpriority string not null,
    o_clerk string not null,
    o_shippriority string not null,
    o_comment string not null,
    constraint fk_custkey foreign key (o_custkey) references customer_hybrid(c_custkey)
);

各テーブルのレコード数は以下の通りです。

Region Nation Customer Orders
5行 25行 15万行 150万行

今回は比較のため、同じカラム定義で通常のテーブルも用意します。

検証に使ったウェアハウス

今回は、Snowflakeでの最小のウェアハウスサイズである「XS」を利用して検証します。今回のデモ環境では、ウェアハウスのサイズを変更することができなかったため、他のサイズでのパフォーマンスについては別の機会に検証したいと思います。

検証その1: トランザクション処理

Hybrid Tableが得意とするトランザクション処理について、通常のTableと比較して、どれくらいのパフォーマンス差異があるのかを検証してみます。

一般的な以下のユースケースについて検証してみます。

  • ある特定の1レコードを取得する (SELECT)
  • ある特定のレコードを追加する (INSERT)
  • ある特定のレコードを更新する (UPDATE)
  • ある特定のレコードを削除する (DELETE)

今回は、連続して5回クエリを発行してみて、クエリパフォーマンスを調べます。

SELECT

Primary Keyをwhere句で指定した形のよくあるクエリを発行してみます。

-- 通常のTable
select * from customer 
where c_custkey = 50000
;

-- Hybrid Table
select * from customer_hybrid
where c_custkey = 50000
;

結果は以下のようになりました。今回はウェアハウスを立ち上げたまま連続で5回クエリしたため、各種キャッシュが効いています。通常のTableの場合、2回目以降はQuery Result Cacheが効いているので30ms程度でレスポンスしています。一方、Hybrid Tableの場合、Query Result Cacheが効かないため、徐々に改善するものの、100ms前後に留まる形となっています。

1回目 2回目 3回目 4回目 5回目
Table 338ms 56ms 42ms 38ms 34ms
Hybrid Table 341ms 167ms 139ms 92ms 98ms

では、より行数の多いテーブルでどうなるかも見てみます。

-- Table
select * from orders
where o_orderkey = 5000000
;

-- Hybrid Table
select * from orders_hybrid
where o_orderkey = 5000000
;
1回目 2回目 3回目 4回目 5回目
Table 1.6s 68ms 44ms 45ms 34ms
Hybrid Table 353ms 256ms 104ms 96ms 92ms

より行数が多いと、通常のテーブルでは初回のクエリにかなり時間がかかるようになった一方、Hybrid Tableではパフォーマンスがあまり低下していません。

INSERT

次に、5回に分けて1レコードずつ追加してインサート処理のパフォーマンスを検証してみたいと思います。

-- 通常のTable
insert into customer
values (0, 'Created', 'xxxxx', 23, '00-000-000-0000', 0.0, 'created', 'created')
;
-- 以下、PKの値を変えてレコードを追加

-- Hybrid Table
insert into customer_hybrid
values (0, 'Created', 'xxxxx', 23, '00-000-000-0000', 0.0, 'created', 'created')
;
1回目 2回目 3回目 4回目 5回目
Table 520ms 407ms 530ms 466ms 835ms
Hybrid Table 223ms 167ms 136ms 183ms 170ms

インサート処理に関しては、明確にHybrid Tableの方が3倍程度早くなっています。

よりデータ量が多いテーブルではどうなるかも見てみます。

-- 通常のTable
insert into orders
values (0, 1, 'O', 100, '2022-08-01', 'xxx', 'xxx', 0, 'created')
;

-- Hybrid Table
insert into orders_hybrid
values (0, 1, 'O', 100, '2022-08-01', 'xxx', 'xxx', 0, 'created')
;
1回目 2回目 3回目 4回目 5回目
Table 629ms 459ms 365ms 482ms 373ms
Hybrid Table 179ms 399ms 160ms 139ms 119ms

どちらのケースでもパフォーマンスはあまり変わりませんでした。

UPDATE

更新処理についても、同じレコードを5回連続で更新してみて、処理速度を確かめてみます。

-- 通常のTable
update customer set c_comment = 'updated'
where c_custkey = 50000
;

-- Hybrid Table
update customer_hybrid set c_comment = 'updated'
where c_custkey = 50000
;
1回目 2回目 3回目 4回目 5回目
Table 3.5s 827ms 997ms 933ms 902ms
Hybrid Table 206ms 211ms 193ms 446ms 189ms

インサート処理に比べると、より差が明確になりました。4-5倍の速度差が生じています。

より大きいテーブルに対しても検証してみます。

-- Table
update orders set o_comment = 'updated'
where o_orderkey = 5000000
;

-- Hybrid Table
update orders_hybrid set o_comment = 'updated'
where o_orderkey = 5000000
;
1回目 2回目 3回目 4回目 5回目
Table 3.0s 1.5s 1.4s 1.4s 1.2s
Hybrid Table 351ms 332ms 172ms 164ms 178ms

通常のTableでは速度低下が見られる一方、Hybrid Tableはほとんど性能劣化していません。

レコードを削除する

最後に、レコードを1つずつ、5回削除してみます。追加処理の検証で作成したレコードを削除していきます。

-- 通常のTable
delete from customer
where c_custkey = 0
;

-- Hybrid Table
delete from customer_hybrid
where c_custkey = 0
;
1回目 2回目 3回目 4回目 5回目
Table 1.2s 602ms 460ms 473ms 307ms
Hybrid Table 337ms 194ms 165ms 160ms 167ms

更新処理ほどではありませんでしたが、こちらも、Hybrid Tableの方が早い結果となりました。

より大きいテーブルでも試してみましたが、どちらの場合でも大きな変化は見られませんでした。

-- 通常のTable
delete from orders
where o_orderkey = 0
;

-- Hybrid Table
delete from customer_hybrid
where c_custkey = 0
;
1回目 2回目 3回目 4回目 5回目
Table 539ms 497ms 529ms 463ms 289ms
Hybrid Table 168ms 207ms 142ms 136ms 143ms

まとめ

トランザクション処理の基本的な操作について、通常のTableとHybrid Tableで比較してみました。
当然ではありますが、Hybrid Tableの方が優位という結果になりました。特に更新処理では大きい差が出ています。

通常のトランザクション処理として考えた場合には、パフォーマンスにやや物足りなさを感じてしまいますが、Hybrid Tableは開発中の機能ですし、今回の検証ではウェアハウスサイズも最小のものしか利用できなかったこともあり、改善の余地は非常にあると考えられます。引き続き今後も検証していきたいと思います。

検証その2: アナリティクス処理

Summitでは、Hybrid TableとTableを組み合わせてデータ分析することができると紹介されていました。実際のユースケースとしても、RDBとDWHのデータを組み合わせて分析したい場合があると思います。そこで、以下の3パターンで、パフォーマンスがどのように変わるかを検証してみます。

  • Tableのみから分析
  • Hybrid Tableのみから分析
  • TableとHybrid Tableを組み合わせて分析

今回は、アジアRegionの顧客の全注文の合計金額を集計するクエリを発行してみます。

Tableのみ / Hybrid Tableのみ から分析

まずは、組み合わせない場合のパフォーマンスについて見てみます。

-- 通常のTableのみで集計
select sum(o_totalprice) from orders o
join customer c on o.o_custkey = c.c_custkey
join nation n on n.n_nationkey = c.c_nationkey
join region r on r.r_regionkey = n.n_regionkey
where r.r_name = 'ASIA'
;

-- Hybrid Tableのみで集計
select sum(o_totalprice) from orders_hybrid o
join customer_hybrid c on o.o_custkey = c.c_custkey
join nation_hybrid n on n.n_nationkey = c.c_nationkey
join region_hybrid r on r.r_regionkey = n.n_regionkey
where r.r_name = 'ASIA'
;
1回目 2回目 3回目 4回目 5回目
Table 3.8s 39ms 33ms 46ms 39ms
Hybrid Table 1m18s 7.4s 7.7s 7.5s 7.3s

通常のTableのみから構成される集計クエリの場合、2回目以降はQuery Result Cacheが効くようになります。一方、Hybrid Tableを含むクエリの場合にはQuery Result Cacheは効かず、毎回処理が行われているようです。

TableとHybrid Tableを組み合わせて分析

-- ordersのみ、hybrid tableを利用する
select sum(o_totalprice) from orders_hybrid o
join customer c on o.o_custkey = c.c_custkey
join nation n on n.n_nationkey = c.c_nationkey
join region r on r.r_regionkey = n.n_regionkey
where r.r_name = 'ASIA'
;

-- customerのみ、hybrid tableを利用する
select sum(o_totalprice) from orders o
join customer_hybrid c on o.o_custkey = c.c_custkey
join nation n on n.n_nationkey = c.c_nationkey
join region r on r.r_regionkey = n.n_regionkey
where r.r_name = 'ASIA'
;

-- order, customerをhybrid tableにする
select sum(o_totalprice) from orders_hybrid o
join customer_hybrid c on o.o_custkey = c.c_custkey
join nation n on n.n_nationkey = c.c_nationkey
join region r on r.r_regionkey = n.n_regionkey
where r.r_name = 'ASIA'
;
1回目 2回目 3回目 4回目 5回目
order, customerがhybrid 7.2s 5.5s 7.1s 6.5s 6.5s
orderのみhybrid 6.7s 6.3s 6.0s 6.3s 8.7s
customerのみhybrid 1.7s 669ms 773ms 236ms 846ms

このjoinの中で最も大きいordersテーブル(150万行)がhybridの場合は、クエリはかなり重たいものになってしまいました。一方で、customer(15万行)のみがhybridになっている場合は、クエリのパフォーマンスは大幅に改善されています。

また、Hybrid Tableのデータを分析に使いたい場合のユースケースの多くは、最新データのみHybrid Tableから取得し、主なデータはTableに既に入っている、という状態だと想像されます。そこで、デモデータ内で最新の日付(1998-08-02)のデータを含まないorders_2テーブルを用意し、最新日のデータのみはHybrid Tableから取得して集計するような以下のクエリも試してみます。

with o as (
    select * from orders_2
    union all
    select * from orders_hybrid where o_orderdate = '1998-08-02'
)
select sum(o_totalprice) from o
join customer_hybrid c on o.o_custkey = c.c_custkey
join nation n on n.n_nationkey = c.c_nationkey
join region r on r.r_regionkey = n.n_regionkey
where r.r_name = 'ASIA'
1回目 2回目 3回目 4回目 5回目
9.5s 8.8s 8.4s 7.5s 7.9s

hybridテーブルからは一部のデータしか利用しないため、高速に処理されることを期待していたのですが、残念ながらselect * from orders_hybrid where o_orderdate = '1998-08-02'の部分の処理が重いため、クエリは高速にはなりませんでした。

まとめ

分析ワークロードでは、通常のテーブルのみのクエリの方が当然高いパフォーマンスを発揮しますが、Hybrid Tableを組み合わせた場合でも、巨大なテーブルでなければ非常に高速に処理できることがわかりました。

アドホックにHybrid TableのデータをDWHのデータと掛け合わせて分析したい、といった用途であれば現段階でも十分実用可能ではないでしょうか。

検証その3: データ同期

では、最後に、Hybrid Tableと通常のTableの間でのデータ同期について検証します。

データ同期の具体的なユースケースとしては、

  • RDBのデータをDWHに同期して分析したい
  • DWHでデータ集計し、集計結果をRDBに保管したい(ReverseETL, Data Activation)

といったことが想定されます。このようなユースケースにどれくらい対応できるのかを調べるため、以下のような検証を実施しました。

  • Hybrid TableからTableへのデータ同期
  • TableからHybrid Tableへのデータ同期

Hybrid TableからTableへのデータインサート

3つのテーブルサイズで、パフォーマンスを比較してみます。

-- 25行
insert into nation
select * from nation_hybrid
;

-- 15万行
insert into customer
select * from customer_hybrid
;

-- 150万行
insert into orders
select * from orders_hybrid
;

結果は以下のようになりました。150万行のテーブルでも20秒以内に取り込めます。最小のウェアハウスでこのパフォーマンスなので、非常に高速だと考えて良いのではないでしょうか。また、ETLツールなどを用いずに、クエリ1行でDWHにRDBデータが取り込めるのは革新的ですね...!

nation (25行) customer (15万行) order (150万行)
460ms 2.4s 17s

なお、CDC(Change Data Capture)で、変更をリアルタイムにDWHに取り込みたいと思うことも多いと思います。Snowflakeには、テーブルの変更を追跡するストリームという機能があり、これを用いるとCDCを実現できます。しかし、残念なことに、現時点ではHybrid Tableに対してストリームを設定することはできませんでした。今後対応してくれることに期待です...!

TableからHybrid Tableへのデータインサート

こちらも、3つのテーブルサイズで、パフォーマンスを比較してみます。

-- 25行
insert into nation_hybrid
select * from nation
;

-- 15万行
insert into customer_hybrid
select * from customer
;

-- 150万行
insert into orders_hybrid
select * from orders
;

結果は以下のようになりました。制約のチェックが入る分、HybridTable->Tableより時間がかかるようになります。また、データ量に対しておおよそ線形にロード時間が伸びているようです。
15万行のbulk insert処理が30秒程度で終わるのであれば、かなり多くのユースケースで実用に耐えるのではないでしょうか。

nation (25行) customer (15万行) order (150万行)
500ms 28s 5m15s

なお、外部キー制約を外すことで、より高速にロードすることが可能です。

終わりに

今回は、Hybrid Tableの各種パフォーマンスについて、現段階での検証を一通り実施してみました。
TableとHybrid Tableを跨いだ分析クエリやデータ同期については現段階でも実用レベルの完成度になっていると感じました。

一方で純粋なOLTP処理についてはまだ改善の余地があると思われますが、トランザクション負荷の小さいアプリケーションやキャッシュを効かせやすいアプリケーションであれば、問題なく使えそうでした。

総じて、今後の開発の期待がより高まる結果となりました! (※記事公開時点では一部のリージョンでPrivate Previewとして提供)

なお、今回の検証の一部は、以下のYoutube Liveにて紹介しておりますので、こちらの動画も是非ご確認いただければと思います。
https://www.youtube.com/watch?v=f_z0M6a30UA

Twitterも始めました。Snowflakeに興味のある皆様と繋がれれば嬉しいです!

Discussion