[GCP] Spanner の Split 分割の観測と考察

[GCP] Spanner の Split 分割の観測と考察

こんばんは、七色メガネです。
今回は、GCP で提供される Spanner における、Split の分割について検証と考察をしてみたいと思います。

Spanner ってなに?

Spanner は、GCP で提供される分散型のRDBです。次の記事で Spanner についての紹介を行なっていますので、よろしければご参照ください。

[ GCP ] メガネと学ぶ GCP (8) ストレージ・サービスの特徴を知る

Split ってなに?

Split とは、Spanner において実際にデータが保存されるデータ単位のことを言います。
次の記事で解説を行なっているので、よろしければご参照ください。

[GCP] Spanner のアーキテクチャを図解する

検証の前置き

では早速ですが、Spanner における Split が分割される事象を観察してみたいと思います。
とは言え、データがその Split に保存されているか、また Split がどのタイミングで分割されるかなどについて、我々は実際に見ることが出来ません。ので、あくまで検証データからの推測の域を出ないことを、あらかじめご了承ください。

Split 分割の発生条件について

1つの Split のデータ上限は 4GB です。Split 内のデータが 4GB を超過する時、Split は分割されデータは分散されます。

[ 公式 ]

https://cloud.google.com/spanner/docs/schema-design#limit_row_size

 

検証の目的

・Split の分割を意図的に発生させるようデータを用意し、Split の分割が発生したことをクエリの実行で確認する。

・Split の分割を意図的に回避するようデータを用意し、Split の分割が発生していないことをクエリの実行で確認する。

 

検証方法

・次の2パターンを試行する。

(A) 1ノードのインスタンスで、PKをあえてシーケンシャルに設定したレコードをテーブルに格納し続け、4GB/8GB 前後でのクエリ性能を観察する。

(B) 1ノードのインスタンスで、PKにUUIDを用いたレコードをテーブルに格納し続け、4GB/8GB 前後でのクエリ性能を観察する。

・クエリ性能は、 where 句無しの count(*) クエリで以って計測する。

検証結果と考察

パターンAの内容

1ノードのインスタンスで、PKをあえてシーケンシャルに設定したレコードをテーブルに格納し続け、4GB/8GB 前後でのクエリ性能を観察する。

パターンAの結果

パターンAの考察

まずはパターンAの考察です。パターンAではシーケンシャルなPKのデータを Insert し続けたので、データは分散されることなく、特定の Split に格納されるはずです。イメージとしては次のような感じです。

1 Split の上限は 4GB なので、それを上回るデータが Split に格納される少し前に、Split は分割されるはずです。
そして検証結果を見てみると、4GB、8GB 付近で、格納データを参照するクエリの処理速度に変化があったことが確認できます。

グラフは、青の線がデータサイズを、赤の線がクエリの実行速度を表しています。

3GB 付近と、5GB 付近と、6GB 付近で、処理速度が早くなっていることが分かります。
ここで生じる疑問は2つです。

1つは、「なぜ 4GB の倍数付近ではなく、3/5/6 GB 位置で変化が見られたのか」と言う点、もう一つは、「なぜ処理速度が早くなったのか」と言う点です。

なぜ処理速度の変化が 3/5/6 GB 位置で起きたのか

これには2つの原因があるのではないかと思います。1つは、「Split の分割は 4GB に達するある程度前に行われる」と言うこと、もう一つは「分割されるSplit先は必ずしも 0GB の Split ではない」と言うことです。

図にしてみましょう。初期の Split 状態がこのようであったと仮定します。
すでに各 Split にはある程度の他のデータが存在しています。

そこで1つの Split を狙い撃ちしてデータを格納し続けると、Split 上限に達するのは、「4GBのデータを格納した時」ではなく、「Split に格納されているデータ総量が4GBに達した時」であることが推測されます。

従って、このように Split 内の他のデータの存在を考え、かつデータ分割は 4GB に達する前に実行されると考えたら、3/5/6 GB 位置で処理速度の変化が起きたのは不思議ではないと言うことができそうです。

 

なぜ処理速度が早くなったのか

では処理速度についてです。これはおそらく、ノード内で Select の分散処理が実行可能になったことによるものではないかと推測します。

Split 分割前のデータ保存イメージは次のように仮定します。Split の中身がいっぱいになっている状態です。

ここでデータ分割が実行されると、Split-A にあったデータが、Split-B に移動します。

これにより、当該データを Select するクエリはノード内で分散実行されることになるため、検証結果における Split 分割時点では処理速度が一時的に加速したのではないか、と推測します。

 

パターンBの内容

1ノードのインスタンスで、PKにUUIDを用いたレコードをテーブルに格納し続け、4GB/8GB 前後でのクエリ性能を観察する。

パターンBの結果

パターンBの考察

では次にパターンBです。パターンAに比べて、処理速度の増加幅が緩やかであることが分かります。
これは、PK に UUID を用いたことで、データが1つの Split に集中しなくなったためだと思われます。

最初から複数の Split にデータの分散が行えているため、データ処理も最初から分散して行われ、処理速度も安定して増加しています。

ただデータ分散を行っているからといって、Split の分割が起きないという訳ではありません。分散先の Split でデータが 4GB に達したならばその時は Split の分割が行われます。

検証試行数が少ないので推測の域を出ませんが、今回の結果で1箇所だけ処理速度が加速したポイントがありましたが、そこが正にそれで、データ分散しながらも Split の分割が起きた場所では無いのかな、と推測します。(推測です。計測誤差かもしれません。)

 

パターンAとBの比較

パターンAとBの比較考察

最後のまとめとして、AとBの比較です。
Aは赤色の線で、PKがシーケンシャルに増加する値を設定した場合です。
Bは黄色の線で、PKにUUIDを設定した場合です。

Bでは総じて緩やかに処理速度の増加が見られるのに対して、Aは増加が急激で、ある程度上昇した時にはガクッと値を下げるという現象が何度か見られます。繰り返しになりますが、これは Split の分割によるものと推測します。

興味深いのは、Aで Split 分割が起きた時の処理速度が、概ね B と同じ程度まで早くなっているということです。
仮に、 B が最初から数十個の Split にデータ分散を行っており、A の分割が 1 Split を 2Split に分割するものであるとすれば、この結果はおかしいです。A で分割が起きたとしても、到底 B の処理速度には近づかないはずです。

この結果から、以下のような仮説を考えてみました。

(仮説1) PK に UUID を用いてデータを分散させたとしても、データは必要以上に多くの Split に振り分けられる訳では無い。
(仮説2) Split の分割が起きるとき、データは複数の Split に分割される。

 

仮説1

データ分散が過剰に行われないと仮定すれば、1つの Split にデータ集中した場合と、データが分散されている場合とでは、瞬間的にはそれほど処理時間に差が出ないことも納得できます。

仮説2

Split の分割は 1 つの Split から 2 つの Split に分割される、と思っていましたが、もし 1 >>> 複数の Split に分割が行われたとしたら、データが Split に集中している場合としていない場合の差異は、前者で Split 分割が生じた時に 0 になるのも理解できます。

 

結果まとめ

観測できたこと

・Split は 4 GB 前後で分割が発生する

・データが分散されていない時、データが分散されている時よりもクエリの処理速度は遅くなる

・1ノードの場合、データが分散の有無に関わらず、それほどクエリの処理速度は変わらない

仮説

・Split が分割される時、データは複数の Split に移行されるのかもしれない

・データが分散されているとしても、過剰に多くの Split にデータが分散されるわけでは無いのかもしれない

反省

・データサイズが小さいので結果に大きな差が見られなかった

・クエリ負荷が小さいので結果に大きな差が見られなかった

・複数ノードでの検証を行えなかった

次回があれば確認したいこと

・データサイズをノード限界の 2 Tまで拡張したい

・マルチスレッドでクエリを発行して処理負荷を与えたい

・3ノード環境で検証を行いたい

参考

https://medium.com/google-cloud-jp/cloud-spanner-%E3%81%AE%E3%83%8F%E3%82%A4%E3%83%AC%E3%83%99%E3%83%AB%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%E8%A7%A3%E8%AA%AC-fee62c17f7ed

https://docs.google.com/presentation/d/1XKaOrex3WS8xZ0TsjsTQKBgxjVSGxkyqdcIqG66zd64/htmlpresent

https://cloud.google.com/spanner/docs/schema-design?hl=ja

https://cloud.google.com/spanner/docs/instances?hl=ja

 

書籍紹介

Google Cloud Platform エンタープライズ設計ガイド

Google Cloud Platform 実践Webアプリ開発 ストーリーで学ぶGoogle App Engine

プログラマのためのGoogle Cloud Platform入門 サービスの全体像からクラウドネイティブアプリケーション構築まで

GoogleCloudPlatformカテゴリの最新記事