Cloud Spanner の裏側
〜解析からベストプラクティスへ〜
Samir Hammoudi (Twitter: @ksimir)
Gaming Technical Specialist, Google Cloud
Confidential & Proprietary
Cloud Spanner の概要
Cloud Spanner のアーキテクチャ解説
Cloud Spanner ベストプラクティス
Agenda
Cloud Spanner の概要
Confidential & Proprietary
Cloud Spanner
Cloud Spanner は、エンタープライズ クラスで唯一の、
グローバルに分散され、強整合性を備えたデータベース
サービスです。リレーショナル データベースの構造と
非リレーショナル データベースの水平スケーラビリティを
兼ね備え、クラウドに特化した設計となっています。
Great apps run on great databases.
Confidential & Proprietary
The best of RDBMS + NoSQL
Confidential & Proprietary
Cloud
Storage
Cloud
Memorystore
(beta)
BigQuery
RelationalNon-relational Object Warehouse
Object storage,
data lake
Managed
Redis
Cloud Datastore/
Cloud Firestore
(beta)
Serverless scalable
document store
Cloud
Bigtable
Low latency,
scalable wide column
store
Cloud
SQL
Managed
MySQL &
PostgreSQL
Cloud
Spanner
Scalable
mission-critical
RDBMS
Enterprise
data warehouse
In-memory
フルマネージドデータサービスのポートフォリオ
Confidential & Proprietary
Relational semantics
Schemas, ACID transactions (across rows), SQL query
+
Horizontal-scale
99.999% SLA, Fully managed, and Easily scalable
Confidential & Proprietary
Google のマネージド・スケーラブル・リレーショナルデータベース・サービス
完全マネージドのグローバルスケールで PB スケールの DB サービス1
2
3
4
ゾーン間・リージョン間の自動 synchronous レプリケーション
スキーマ、ACID トランザクション、SQL
Google内部では、既に5年以上の運用経験
(AdWords, Google Play…)
Cloud Spanner とは?
Confidential & Proprietary
● 1ノードごとに3つのレプリカ
JP region
Cloud Spanner Instance
JP zone a JP zone b JP zone c
1 2 3
RW RW RW
展開モデルーシングルリージョン
Confidential & Proprietary
展開モデルーマルチリージョン
● 1ノードごとに9つのレプリカ
Confidential & Proprietary
US Datacenter EU Datacenter
Time MastersTime Masters
時刻同期 時刻同期
原子時計 原子時計
GPS受信機 GPS受信機
Spanner
Node
Spanner
Node
Spanner
Node
Spanner
Node
Spanner
Node
Spanner
Node
Time Masters
Armageddon
Masters
GPS Masters
Cloud Spanner の時刻同期(TrueTime API)
Confidential & Proprietary
可用性とパフォーマンスのために常に複製
Cloud Spanner instance
Zone A Zone B Zone C
DB 1
DB 2
DB 1
DB 2
DB 1
DB 2
Confidential & Proprietary
Data is synchronously replicated using Paxos consensus.
Update
Cloud Spanner instance
Zone A Zone B Zone C
DB 1
DB 2
DB 1
DB 2
DB 1
DB 2
Synchronous レプリケーションと高整合性
Cloud Spanner のアーキテクチャ解析
Confidential & Proprietary
API
Files
Node
Server
API
Files
Node
Server
API
Files
Node
Server
API
Files
Node
Server
API
Files
Node
Server
API
Files
Node
Server
Client Clients
API Server
Node Tier
Filesystem
Zone 1 Zone 2 Zone 3
Cloud Spanner     のアーキテクチャ
Confidential & Proprietary
● Channels
○ Cloud Spanner へ接続する gRPC コネクション数
○ Default = 4, max = 256.
○ コードの中で定義する必要がある
■ SpannerOptions options = SpannerOptions.newBuilder().setNumChannels(8).build();
● Sessions
○ Session はトランザクションを実行できるコンテキストです。並列で行われる
トランザクションは各自 session を利用する必要がある。例えば、あるアプリが並列に
100トランザクションを行うとしたら、 Session pool を最低100に設定する必要があります。
○ Default value = Default number of channels * 100 = 400
○ Recommendations: Number of sessions = number of expected threads
○ データベースごとにセッション数の上限が: 10000 per node.
○ 詳細はこちら:https://cloud.google.com/spanner/docs/sessions?hl=ja
Channels と Sessions
Confidential & Proprietary
Channels と Sessions
Thread
Spanner
session pool
Thread
Thread
Session in use Idle session
Spanner Client application Spanner instance
Spanner channel
(gRPC connection)
Confidential & ProprietaryZone 1
NS NS NS NS ノード = Node Servers
2TB まで管理できるサーバ
Colossus (分散ストレージ)
実データはここに格納される
C クライアント
Split
ノード数:4
各ノードは
複数の Split の
オーナー
Cloud Spanner のアーキテクチャ
Confidential & Proprietary
id (PK) name address gender
101 samir tokyo m
102 hassy tokyo m
:
1001
1002
:
2001
2002
Table
Data Split 1
Data Split 2
Data Split 3
Key 101~1000
Key 1001~2000
Key 2001~2999
Split とは?
Confidential & Proprietary
NS NS NS NS
Zone 1 Zone 2
G-NA-F S-ZO-R G-NA-F S-Z O-R
Splits
Node Servers
100% Key Coverage
per Zone
Split のレイアウト
Confidential & Proprietary
NS NS NS NS
Zone 1 Zone 2
G-NA-F S-ZO-R G-NA-F S-Z O-R
A-C D-F A-C D-F
Split の分割
Confidential & Proprietary
NS NS NS NS
Zone 1 Zone 2
G-NA-F S-ZO-R G-NA-F S-Z O-R
New NS
G-N
New NS
O-R
Split の移動
Confidential & Proprietary
Paxos プロトコルが利用されるため、 レプリカの大部分が投票したら、コミット は行われる
→ 例えば、2大陸のMRの構成でレプリカが5台ある場合( 4 x RW + Witness = 5 replicas)
→ 書き込みのコミットは3台のレプリカが投票してら行われる
US regionEU region
eu-west1 eu-west1 us-central1 us-central1 us-central2 us-central2 witness
RO RO RW RW RW RW W
5レプリカのうち、3レプリカが投票するとコミットが行われる投票しない
書き込みのコミットの仕組み
Confidential & Proprietary
プライマリリージョン (Primary region)
→ リーダーレプリカが配置されるリージョン
→ 書き込みコミットの投票に利用されるリージョン
セカンダリリージョン (Secondary region)
→ リーダーとして選択可能とされるレプリカが配置されるリージョン
→ 地理的にプライマリリージョンに近く配置( 1000マイル以下)
→ 書き込みコミットの投票に利用されるリージョン
ウィットネスリージョン(Witness region)
→ 書き込みコミットの投票のみに利用されるリージョン
→ セカンダリとプライマリは地域的にウィットネスより近いため、
普段はウィットネスの投票は影響なし
リージョタイプ
Confidential & Proprietary
Read Write レプリカ
→ リーダーとして選択可能
→ コミットの投票に参加する
Read Only レプリカ
→ リーダーになれない
→ コミットの投票に参加しない
ウィットネスレプリカ
→ リーダーにはなれない
→ リーダーの選択には参加
→ コミットの投票に参加する
リーダーとは?
→ Split への RW を管理するレプリカ
RW RW RW RW
Split
Split のリーダー
レプリカタイプ
Confidential & Proprietary
Cloud Spanner には2種類のトランザクション:
1. Locking read-write transaction (mutation)
a. 悲観的ロック
a. 読み書きするセルのみをロック
2. Read-only transaction
a. 3 種類
i. Strong (デフォルト) :最新のデータを読む
ii. Bounded staleness:指定した範囲から最新のデータを読む
iii. Exact staleness:指定したタイムスタンプのデータを読む
b. ロックを行わない
トランザクションタイプ
Cloud Spanner のベストプラクティス
Confidential & Proprietary
PK のベストプラクティス
シナリオ:
● MySQL から Cloud Spanner の移行
ステップ:
● MySQL からデータを CSV として Dump する
● GCS にアップロード
● データロード用のプログラムを GCE インスタンス上で実行
● Cloud Spanner へデータをロード
問題:
● Auto-increment の PK のスキーマをそのままインポート
Confidential & Proprietary
Confidential & Proprietary
3 ノードから
5 ノードに増加しても、
CPU 使用率が上がらず
パフォーマンスも上らない
ノード数を増加してら、 CPU
使用率が 35% から
20% に下がった
ノード数を増加しても、
パフォーマンスは上らず
HOTSPOT
の現象
35%
20%
3
5
7000 QPS
Confidential & Proprietary
HOTSPOT
とは?
同じノードに
書き込みが
集中する問題
Confidential & Proprietary
Hotspot の対策
解決策:
1. ランダムの順でデータを Cloud Spanner にインポートする
a. PK の順ではホットスポット
2. 新しい PK を作る
a. Auto-increment の INT64 の代わりに STRING32 に UUIDv4 を利用する
Confidential & Proprietary
Confidential & Proprietary
5 ノードを設定
スループットが 7000 QPS 程
度から 25000 QPS まで上
がった!
CPU 使用率もようやく
100% をヒットした!
HOTSPOT
解決!
3
5
100%
25000 QPS
Confidential & Proprietary
データのローカリティ
問題:
● Cloud Spanner は分散データベース
● どのデータがどのノードにあるかは想定できない
● JOIN クエリのパフォーマンスが心配
1111 john
1122 paul
1234 bob
1111 001
1111 002
1234 001
Spanserver A Spanserver B
SELECT user_name, item_id FROM users INNER JOIN items ON users.user_id = items.user_id WHERE user_id = 1234;
user_id user_name
1111 john
1122 paul
1234 bob
user_id item_id
1111 001
1111 002
1234 001
Confidential & Proprietary
Interleaving
Interleaving(インターリービング)
● Cloud Spanner は PK の値によってソートされた順序でレコードを格納し、同じ PK のプレフィック
スを共有する親のレコード間に子のレコードを挿入します。
● 子テーブルは「Interleave Table」と呼ばれる
Confidential & Proprietary
Sibling テーブル - 論理的なデータレイアウト
CREATE TABLE Singers (
SingerId INT64 NOT NULL,
FirstName STRING(1024),
LastName STRING(1024),
SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);
CREATE TABLE Albums (
SingerId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX),
) PRIMARY KEY (SingerId,
AlbumId);
Confidential & Proprietary
Sibling テーブル - 物理的なデータレイアウト
Confidential & Proprietary
Interleave テーブル - 論理的なデータレイアウト
CREATE TABLE Singers (
SingerId INT64 NOT NULL,
FirstName STRING(1024),
LastName STRING(1024),
SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);
CREATE TABLE Albums (
SingerId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId);
INTERLEAVE IN PARENT Singers ON DELETE
CASCADE;
Confidential & Proprietary
Interleave テーブル - 物理的なデータレイアウト
Confidential & Proprietary
Interleave テーブルの階層 - 論理的ビュー
CREATE TABLE Singers (
SingerId INT64 NOT NULL,
FirstName STRING(1024),
LastName STRING(1024),
SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);
CREATE TABLE Albums (
SingerId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId),
INTERLEAVE IN PARENT Singers ON DELETE CASCADE;
CREATE TABLE Songs (
SingerId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
TrackId INT64 NOT NULL,
SongName STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId, TrackId),
INTERLEAVE IN PARENT Albums ON DELETE CASCADE;
Confidential & Proprietary
Interleave テーブルの階層 - 物理的ビュー
Confidential & Proprietary
なぜテーブルを
インターリーブするか
user_id
SELECT user_name, item_id FROM users INNER JOIN items ON users.user_id = items.user_id WHERE user_id = 1234;
user_id user_name
1111 john
1122 paul
1234 bob
user_id item_id
1111 001
1111 002
1234 001
user_name
user_id
item_id
1111 john
1122 paul
1234 bob
1111 001
1111 002
1234 001
Spanserver A Spanserver B
1111 john
1111 001
1111 002
1122 paul
1234 bob
1234 001
Spanserver A
Logical View Physical View
No interleave
Physical View
With interleave
インタリーブをすると、 JOIN   クエリ
が2つのサーバにアクセスすることも
なく、1サーバで済む
Confidential & Proprietary
負荷試験
シナリオ:
● 負荷試験を行っており、負荷ツールである負荷シナリオを5分間実行する
問題:
● 5分間負荷試験を実行したが、思った通りにパフォーマンスがでない
Confidential & Proprietary
負荷試験は十分長く実行する
Cloud Spanner の負荷試験を行う場合、5分ではなく、20〜30分の負荷試験をオススメします。その理由は、データの容量
が多くなることにより、Split がより多く発生して、データが正常に全ノード間に分散されるからです。
テーブルが十分 split されると、全ノードが
活用され、Cloud Spanner の最大の
パフォーマンスを出せるようになります。
Split
happens
Confidential & Proprietary
Cloud Spanner は容量と負荷状況次第、テーブルを split します。
ただし、実際にどのタイミングでテーブルが分割されるかは保証できません。
Cloud Spanner では以下の2つの条件でテーブルが分割されます:
● Size-based splits
○ テーブルの容量が数 GB程度になったら、テーブルを split します
● Load-based splits
○ Cloud Spanner は分散できる負荷だと、テーブルを split します。
分散できない負荷は、例えばシーケンシャルな INSERT
上記は、どれだけ PK の選択肢が重要かを示しています。
テーブルが分割(Split)されるロジック
Confidential & Proprietary
負荷試験を毎回行う際は、Insert したデータを全て削除するのではなく、データベースを Drop するようオススメします。
データの削除+再Insert は、テーブルスキャンのパフォーマンスを劣化します。それは、削除されたデータは Garbage
Collector が物理的に削除するまではテーブルに append されるからです。テーブルのクリーンアップまで1週間までかかり
ます。
Spanner のストレージは log-structured merge trees (LSM Tree)を使用している。
→ Delete のオペレーションは "append a delete mutation" とストレージレベルで見られる。古いデータはデータベースがク
リーンアップされるまで削除されない。
→ 削除された PK がまだ格納されているので、テーブルスキャンがインパクトされる。
負荷試験間はデータベースをDropする
Confidential & Proprietary
パフォーマンス
問題解決
100% 負荷試験完了
すぐにMaxが出る
Confidential & Proprietary
Confidential & Proprietary
よく聞かれる2点
● Index を利用するには、明示的に指定する必要がある
FROM MyTable@{FORCE_INDEX=MyTableIndex}
● Index の STORING 機能を利用して、元テーブルにアクセスを避ける
CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING
(MarketingBudget)
Confidential & Proprietary
Query Plan Cache
SQL クエリを Spanner で使用する際に、bound parameters を使用す
るのが重要です。
Cloud Spanner のノードは query plan cache の数が限られています。
クエリの中に静的パラメータを使用すると、各クエリが違うものと見られ
て、query plan cache を効果的に活用することができません。この問題
を避けるには、以下の例のようにクエリは parameter binding を利用す
る必要があります。
Statement statement = Statement
.newBuilder("SELECT name WHERE id > @msg_id AND
id < @msg_id + 100")
.bind("msg_id").to(500)
.build();
これ重要!
Confidential & Proprietary
Cloud
SQL
Cloud
Spanner
Cloud
Datastore
Cloud
Bigtable
BigQuery
Cloud
Firestore on
Firebase
Is your data
structured?
Is your workload
analytics?
Is your data
relational?
Do you need updates
or low-latency?
Do you need
Mobile SDK’s?
Do you need
horizontal scalability?
No
Yes
No
Yes
No
Yes
YesNo YesNo Yes No
Do you need
Mobile SDK’s?
Firebase
Storage
YesNo
Cloud
Storage
Confidential & Proprietary
Q&A
Confidential & Proprietary
イノベーションのために時間を作ろう!
Focus on value add and
innovation instead of
maintenance.
Simplify costing to better
understand your app.
Ensure your app stays online
and more secure - 99.999%
SLA.
Confidential & Proprietary
Thank you

[db analytics showcase Sapporo 2018] B13 Cloud Spanner の裏側〜解析からベストプラクティスへ〜

  • 1.
    Cloud Spanner の裏側 〜解析からベストプラクティスへ〜 SamirHammoudi (Twitter: @ksimir) Gaming Technical Specialist, Google Cloud
  • 2.
    Confidential & Proprietary CloudSpanner の概要 Cloud Spanner のアーキテクチャ解説 Cloud Spanner ベストプラクティス Agenda
  • 3.
  • 4.
    Confidential & Proprietary CloudSpanner Cloud Spanner は、エンタープライズ クラスで唯一の、 グローバルに分散され、強整合性を備えたデータベース サービスです。リレーショナル データベースの構造と 非リレーショナル データベースの水平スケーラビリティを 兼ね備え、クラウドに特化した設計となっています。 Great apps run on great databases.
  • 5.
    Confidential & Proprietary Thebest of RDBMS + NoSQL
  • 6.
    Confidential & Proprietary Cloud Storage Cloud Memorystore (beta) BigQuery RelationalNon-relationalObject Warehouse Object storage, data lake Managed Redis Cloud Datastore/ Cloud Firestore (beta) Serverless scalable document store Cloud Bigtable Low latency, scalable wide column store Cloud SQL Managed MySQL & PostgreSQL Cloud Spanner Scalable mission-critical RDBMS Enterprise data warehouse In-memory フルマネージドデータサービスのポートフォリオ
  • 7.
    Confidential & Proprietary Relationalsemantics Schemas, ACID transactions (across rows), SQL query + Horizontal-scale 99.999% SLA, Fully managed, and Easily scalable
  • 8.
    Confidential & Proprietary Googleのマネージド・スケーラブル・リレーショナルデータベース・サービス 完全マネージドのグローバルスケールで PB スケールの DB サービス1 2 3 4 ゾーン間・リージョン間の自動 synchronous レプリケーション スキーマ、ACID トランザクション、SQL Google内部では、既に5年以上の運用経験 (AdWords, Google Play…) Cloud Spanner とは?
  • 9.
    Confidential & Proprietary ●1ノードごとに3つのレプリカ JP region Cloud Spanner Instance JP zone a JP zone b JP zone c 1 2 3 RW RW RW 展開モデルーシングルリージョン
  • 10.
  • 11.
    Confidential & Proprietary USDatacenter EU Datacenter Time MastersTime Masters 時刻同期 時刻同期 原子時計 原子時計 GPS受信機 GPS受信機 Spanner Node Spanner Node Spanner Node Spanner Node Spanner Node Spanner Node Time Masters Armageddon Masters GPS Masters Cloud Spanner の時刻同期(TrueTime API)
  • 12.
    Confidential & Proprietary 可用性とパフォーマンスのために常に複製 CloudSpanner instance Zone A Zone B Zone C DB 1 DB 2 DB 1 DB 2 DB 1 DB 2
  • 13.
    Confidential & Proprietary Datais synchronously replicated using Paxos consensus. Update Cloud Spanner instance Zone A Zone B Zone C DB 1 DB 2 DB 1 DB 2 DB 1 DB 2 Synchronous レプリケーションと高整合性
  • 14.
  • 15.
    Confidential & Proprietary API Files Node Server API Files Node Server API Files Node Server API Files Node Server API Files Node Server API Files Node Server ClientClients API Server Node Tier Filesystem Zone 1 Zone 2 Zone 3 Cloud Spanner     のアーキテクチャ
  • 16.
    Confidential & Proprietary ●Channels ○ Cloud Spanner へ接続する gRPC コネクション数 ○ Default = 4, max = 256. ○ コードの中で定義する必要がある ■ SpannerOptions options = SpannerOptions.newBuilder().setNumChannels(8).build(); ● Sessions ○ Session はトランザクションを実行できるコンテキストです。並列で行われる トランザクションは各自 session を利用する必要がある。例えば、あるアプリが並列に 100トランザクションを行うとしたら、 Session pool を最低100に設定する必要があります。 ○ Default value = Default number of channels * 100 = 400 ○ Recommendations: Number of sessions = number of expected threads ○ データベースごとにセッション数の上限が: 10000 per node. ○ 詳細はこちら:https://cloud.google.com/spanner/docs/sessions?hl=ja Channels と Sessions
  • 17.
    Confidential & Proprietary Channelsと Sessions Thread Spanner session pool Thread Thread Session in use Idle session Spanner Client application Spanner instance Spanner channel (gRPC connection)
  • 18.
    Confidential & ProprietaryZone1 NS NS NS NS ノード = Node Servers 2TB まで管理できるサーバ Colossus (分散ストレージ) 実データはここに格納される C クライアント Split ノード数:4 各ノードは 複数の Split の オーナー Cloud Spanner のアーキテクチャ
  • 19.
    Confidential & Proprietary id(PK) name address gender 101 samir tokyo m 102 hassy tokyo m : 1001 1002 : 2001 2002 Table Data Split 1 Data Split 2 Data Split 3 Key 101~1000 Key 1001~2000 Key 2001~2999 Split とは?
  • 20.
    Confidential & Proprietary NSNS NS NS Zone 1 Zone 2 G-NA-F S-ZO-R G-NA-F S-Z O-R Splits Node Servers 100% Key Coverage per Zone Split のレイアウト
  • 21.
    Confidential & Proprietary NSNS NS NS Zone 1 Zone 2 G-NA-F S-ZO-R G-NA-F S-Z O-R A-C D-F A-C D-F Split の分割
  • 22.
    Confidential & Proprietary NSNS NS NS Zone 1 Zone 2 G-NA-F S-ZO-R G-NA-F S-Z O-R New NS G-N New NS O-R Split の移動
  • 23.
    Confidential & Proprietary Paxosプロトコルが利用されるため、 レプリカの大部分が投票したら、コミット は行われる → 例えば、2大陸のMRの構成でレプリカが5台ある場合( 4 x RW + Witness = 5 replicas) → 書き込みのコミットは3台のレプリカが投票してら行われる US regionEU region eu-west1 eu-west1 us-central1 us-central1 us-central2 us-central2 witness RO RO RW RW RW RW W 5レプリカのうち、3レプリカが投票するとコミットが行われる投票しない 書き込みのコミットの仕組み
  • 24.
    Confidential & Proprietary プライマリリージョン(Primary region) → リーダーレプリカが配置されるリージョン → 書き込みコミットの投票に利用されるリージョン セカンダリリージョン (Secondary region) → リーダーとして選択可能とされるレプリカが配置されるリージョン → 地理的にプライマリリージョンに近く配置( 1000マイル以下) → 書き込みコミットの投票に利用されるリージョン ウィットネスリージョン(Witness region) → 書き込みコミットの投票のみに利用されるリージョン → セカンダリとプライマリは地域的にウィットネスより近いため、 普段はウィットネスの投票は影響なし リージョタイプ
  • 25.
    Confidential & Proprietary ReadWrite レプリカ → リーダーとして選択可能 → コミットの投票に参加する Read Only レプリカ → リーダーになれない → コミットの投票に参加しない ウィットネスレプリカ → リーダーにはなれない → リーダーの選択には参加 → コミットの投票に参加する リーダーとは? → Split への RW を管理するレプリカ RW RW RW RW Split Split のリーダー レプリカタイプ
  • 26.
    Confidential & Proprietary CloudSpanner には2種類のトランザクション: 1. Locking read-write transaction (mutation) a. 悲観的ロック a. 読み書きするセルのみをロック 2. Read-only transaction a. 3 種類 i. Strong (デフォルト) :最新のデータを読む ii. Bounded staleness:指定した範囲から最新のデータを読む iii. Exact staleness:指定したタイムスタンプのデータを読む b. ロックを行わない トランザクションタイプ
  • 27.
  • 28.
    Confidential & Proprietary PKのベストプラクティス シナリオ: ● MySQL から Cloud Spanner の移行 ステップ: ● MySQL からデータを CSV として Dump する ● GCS にアップロード ● データロード用のプログラムを GCE インスタンス上で実行 ● Cloud Spanner へデータをロード 問題: ● Auto-increment の PK のスキーマをそのままインポート
  • 29.
  • 30.
    Confidential & Proprietary 3ノードから 5 ノードに増加しても、 CPU 使用率が上がらず パフォーマンスも上らない ノード数を増加してら、 CPU 使用率が 35% から 20% に下がった ノード数を増加しても、 パフォーマンスは上らず HOTSPOT の現象 35% 20% 3 5 7000 QPS
  • 31.
  • 32.
    Confidential & Proprietary Hotspotの対策 解決策: 1. ランダムの順でデータを Cloud Spanner にインポートする a. PK の順ではホットスポット 2. 新しい PK を作る a. Auto-increment の INT64 の代わりに STRING32 に UUIDv4 を利用する
  • 33.
  • 34.
    Confidential & Proprietary 5ノードを設定 スループットが 7000 QPS 程 度から 25000 QPS まで上 がった! CPU 使用率もようやく 100% をヒットした! HOTSPOT 解決! 3 5 100% 25000 QPS
  • 35.
    Confidential & Proprietary データのローカリティ 問題: ●Cloud Spanner は分散データベース ● どのデータがどのノードにあるかは想定できない ● JOIN クエリのパフォーマンスが心配 1111 john 1122 paul 1234 bob 1111 001 1111 002 1234 001 Spanserver A Spanserver B SELECT user_name, item_id FROM users INNER JOIN items ON users.user_id = items.user_id WHERE user_id = 1234; user_id user_name 1111 john 1122 paul 1234 bob user_id item_id 1111 001 1111 002 1234 001
  • 36.
    Confidential & Proprietary Interleaving Interleaving(インターリービング) ●Cloud Spanner は PK の値によってソートされた順序でレコードを格納し、同じ PK のプレフィック スを共有する親のレコード間に子のレコードを挿入します。 ● 子テーブルは「Interleave Table」と呼ばれる
  • 37.
    Confidential & Proprietary Siblingテーブル - 論理的なデータレイアウト CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), LastName STRING(1024), SingerInfo BYTES(MAX), ) PRIMARY KEY (SingerId); CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX), ) PRIMARY KEY (SingerId, AlbumId);
  • 38.
    Confidential & Proprietary Siblingテーブル - 物理的なデータレイアウト
  • 39.
    Confidential & Proprietary Interleaveテーブル - 論理的なデータレイアウト CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), LastName STRING(1024), SingerInfo BYTES(MAX), ) PRIMARY KEY (SingerId); CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX), ) PRIMARY KEY (SingerId, AlbumId); INTERLEAVE IN PARENT Singers ON DELETE CASCADE;
  • 40.
    Confidential & Proprietary Interleaveテーブル - 物理的なデータレイアウト
  • 41.
    Confidential & Proprietary Interleaveテーブルの階層 - 論理的ビュー CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), LastName STRING(1024), SingerInfo BYTES(MAX), ) PRIMARY KEY (SingerId); CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX), ) PRIMARY KEY (SingerId, AlbumId), INTERLEAVE IN PARENT Singers ON DELETE CASCADE; CREATE TABLE Songs ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, TrackId INT64 NOT NULL, SongName STRING(MAX), ) PRIMARY KEY (SingerId, AlbumId, TrackId), INTERLEAVE IN PARENT Albums ON DELETE CASCADE;
  • 42.
    Confidential & Proprietary Interleaveテーブルの階層 - 物理的ビュー
  • 43.
    Confidential & Proprietary なぜテーブルを インターリーブするか user_id SELECTuser_name, item_id FROM users INNER JOIN items ON users.user_id = items.user_id WHERE user_id = 1234; user_id user_name 1111 john 1122 paul 1234 bob user_id item_id 1111 001 1111 002 1234 001 user_name user_id item_id 1111 john 1122 paul 1234 bob 1111 001 1111 002 1234 001 Spanserver A Spanserver B 1111 john 1111 001 1111 002 1122 paul 1234 bob 1234 001 Spanserver A Logical View Physical View No interleave Physical View With interleave インタリーブをすると、 JOIN   クエリ が2つのサーバにアクセスすることも なく、1サーバで済む
  • 44.
    Confidential & Proprietary 負荷試験 シナリオ: ●負荷試験を行っており、負荷ツールである負荷シナリオを5分間実行する 問題: ● 5分間負荷試験を実行したが、思った通りにパフォーマンスがでない
  • 45.
    Confidential & Proprietary 負荷試験は十分長く実行する CloudSpanner の負荷試験を行う場合、5分ではなく、20〜30分の負荷試験をオススメします。その理由は、データの容量 が多くなることにより、Split がより多く発生して、データが正常に全ノード間に分散されるからです。 テーブルが十分 split されると、全ノードが 活用され、Cloud Spanner の最大の パフォーマンスを出せるようになります。 Split happens
  • 46.
    Confidential & Proprietary CloudSpanner は容量と負荷状況次第、テーブルを split します。 ただし、実際にどのタイミングでテーブルが分割されるかは保証できません。 Cloud Spanner では以下の2つの条件でテーブルが分割されます: ● Size-based splits ○ テーブルの容量が数 GB程度になったら、テーブルを split します ● Load-based splits ○ Cloud Spanner は分散できる負荷だと、テーブルを split します。 分散できない負荷は、例えばシーケンシャルな INSERT 上記は、どれだけ PK の選択肢が重要かを示しています。 テーブルが分割(Split)されるロジック
  • 47.
    Confidential & Proprietary 負荷試験を毎回行う際は、Insertしたデータを全て削除するのではなく、データベースを Drop するようオススメします。 データの削除+再Insert は、テーブルスキャンのパフォーマンスを劣化します。それは、削除されたデータは Garbage Collector が物理的に削除するまではテーブルに append されるからです。テーブルのクリーンアップまで1週間までかかり ます。 Spanner のストレージは log-structured merge trees (LSM Tree)を使用している。 → Delete のオペレーションは "append a delete mutation" とストレージレベルで見られる。古いデータはデータベースがク リーンアップされるまで削除されない。 → 削除された PK がまだ格納されているので、テーブルスキャンがインパクトされる。 負荷試験間はデータベースをDropする
  • 48.
  • 49.
  • 50.
    Confidential & Proprietary よく聞かれる2点 ●Index を利用するには、明示的に指定する必要がある FROM MyTable@{FORCE_INDEX=MyTableIndex} ● Index の STORING 機能を利用して、元テーブルにアクセスを避ける CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget)
  • 51.
    Confidential & Proprietary QueryPlan Cache SQL クエリを Spanner で使用する際に、bound parameters を使用す るのが重要です。 Cloud Spanner のノードは query plan cache の数が限られています。 クエリの中に静的パラメータを使用すると、各クエリが違うものと見られ て、query plan cache を効果的に活用することができません。この問題 を避けるには、以下の例のようにクエリは parameter binding を利用す る必要があります。 Statement statement = Statement .newBuilder("SELECT name WHERE id > @msg_id AND id < @msg_id + 100") .bind("msg_id").to(500) .build(); これ重要!
  • 52.
    Confidential & Proprietary Cloud SQL Cloud Spanner Cloud Datastore Cloud Bigtable BigQuery Cloud Firestoreon Firebase Is your data structured? Is your workload analytics? Is your data relational? Do you need updates or low-latency? Do you need Mobile SDK’s? Do you need horizontal scalability? No Yes No Yes No Yes YesNo YesNo Yes No Do you need Mobile SDK’s? Firebase Storage YesNo Cloud Storage
  • 53.
  • 54.
    Confidential & Proprietary イノベーションのために時間を作ろう! Focuson value add and innovation instead of maintenance. Simplify costing to better understand your app. Ensure your app stays online and more secure - 99.999% SLA.
  • 55.