超実践 cloud spanner 設計講座
TRANSCRIPT
![Page 1: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/1.jpg)
超実践 Cloud Spanner 設計講座知ってることを全て紹介します!
Proprietary
Samir Hammoudi aka サミールクラウドカスタマエンジニア
JULY 21, 2017
![Page 2: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/2.jpg)
Cloud Spanner とは?
Google のマネージド・スケーラブル・リレーショナルデータベース・サービス
完全マネージドのグローバルスケールで DB サービス1
2
3
4
ゾーン間・リージョン間の自動 synchronous レプリケーション
スキーマ、ACID トランザクション、SQL
Google内部では、既に5年以上の運用経験(AdWords, Google Play…)
![Page 3: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/3.jpg)
注意事項:Cloud Spanner ≠ MySQL
Cloud Spanner は MySQL の単なる置き換えではない
● スキーマは似てるが、分散データベースのため、MySQLと違う可能性がある
● SQL の SELECT系とDDLは対応済み、DML も対応予定
→ 現時点では Mutation オブジェクトを利用して INSERT/UPDATE/DELETE を行う
● Auto-increment がない(Spannerではアンチパターンだから)
● MySQL 互換ではない(Spannerのクライアントライブラリを提供)
● パフォーマンスのプロファイルが違う(Scale-up DB vs Scale-out DB)→ 高負荷をかけても Cloud Spanner のレイテンシは安定(Quizletの事例をご参考ください)
● Cloud Spanner では PK の選択がクリティカル ←これ何回言っても足りないので赤にしました!
● FK が存在しない(Spanner では Interleave が FK 相当)
MySQL とは似てるところも色々あるが、Cloud Spanner は分散データベースだということを忘れないでね!!
![Page 4: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/4.jpg)
MySQL ではないが...
特に大規模アクセスのあるコンテンツやDB運用に苦労しているサービスに最適!
ノードを追加するだけでオートシャードされ、理論上無限にスケールしつつ、
レイテンシーがより安定 :)運用も楽 ^_^
![Page 5: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/5.jpg)
今日のおさらいリスト
1. PK の選択が重要 ←これが1番重要!!
2. なぜテーブルをインターリーブするか?
3. インデックスとインターリーブについて
4. Channels と Sessions5. ノード追加・削除の際、リシャードがなぜ1〜2sでできるのか?
6. エラーについて
7. 容量に関する上限 8. テーブルが分割(Split)されるロジック
9. 負荷試験は十分長く実行する
10. 負荷試験間はデータベースをDropする
11. TPSの数え方
12. ノード数を縮小するについて
13. グラフの ”Total storage” の意味って?
14. Query Plan Cache ←これも重要!!
![Page 6: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/6.jpg)
PK の選択が重要
● シーケンシャルな PK を使わないこと → hotspots が発生する
○ auto-increment PK を使わない (even though it doesn’t exist in Cloud Spanner!)○ 時系列の PK を使わない
● MySQL の auto-increment を使用しているテーブルを Spanner にインポートする場合は:
○ 新しい PK を作り、乱数をオススメします (e.g. UUID).○ 元の PK から 計算する shard_id を作る (e.g. shard_id = hash(auto-inc_id)).○ シーケンシャルな PK を使うが、DB に格納する前やクエリーする時はビットを逆にする
● UUID が一番おすすめとしている PK です。
これ重要!
![Page 7: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/7.jpg)
PKを選択する時の注意点 - Hotspot (1/2)
● Hotspot とは、データが Spanner サーバー間にちゃんと分散されない現象
○ 1つの Spanner サーバーに書き込みが集中して、パフォーマンスが減少
○ 同じサーバーを利用するサービスにインパクトも可能
● 現象の理由
○ 新しく書き込まれるレコードはテーブルの最後に追加されて、同じ Spanner サーバーに格納
される(時系列のPK)
CREATE TABLE Users ( LastAccessTimestamp INT64 NOT NULL, UserId INT64 NOT NULL, ...) PRIMARY KEY (LastAccessTimestamp, UserId);
![Page 8: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/8.jpg)
PKを選択する時の注意点 - Hotspot (2/2)
● Hotspot の対策
○ PK の順序を交換
○ 新しく書き込まれるレコードは、テーブルの最後に追加されず、 Spanner サーバー間にちゃんと分散される
CREATE TABLE Users ( UserId INT64 NOT NULL, LastAccessTimestamp INT64 NOT NULL, ...) PRIMARY KEY (UserId, LastAccessTimestamp);
![Page 9: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/9.jpg)
なぜテーブルをインターリーブするか
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 B1111 john
1111 001
1111 002
1122 paul
1234 bob
1234 001
Spanserver A
Logical View Physical ViewNo interleave
Physical ViewWith interleave
インタリーブをすると、 JOIN クエリが2つのサーバにアクセスすることもなく、1サーバで済む
![Page 10: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/10.jpg)
インデックスとインターリーブについて
テーブルがインターリーブされている場合、不要なインデックスを作っているかもしれません。
See the example below:
Table DDL index
user
CREATE TABLE test_user (user_id INT64 NOT NULL,create_date TIMESTAMP NOT NULL) PRIMARY KEY (user_id)
CREATE INDEX idx_user_idON user (user_id)
item
CREATE TABLE test_item (user_id INT64 NOT NULL,item_id INT64 NOT NULL) PRIMARY KEY (user_id, item_id),INTERLEAVE IN PARENT user ON DELETE CASCADE
CREATE INDEX idx_user_id_in_itemON item (user_id)
この例ではセカンダリインデックスは不要です
PK は自動的に インデックスされる
user_id は既に親テーブルでインデックスされている
![Page 11: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/11.jpg)
Channels と sessions
● 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
![Page 12: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/12.jpg)
エラー (auto-retry or SpannerException)
Cloud Console 上のグラフにエラーが発生する場合
があります。
● エラーの原因は通常トランザクションが abort されたからです
● エラーが発生したとグラフで見えるが、コード
の中で SpannerException をキャッチできな
い
● それはクライアントライブラリが自動的に abort されたトランザクションをリトライするか
らです
● 自動リトライが失敗すると、 SpannerException をキャッチできます
● 基本エラーは無視しても問題ありません
![Page 13: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/13.jpg)
ノード追加・削除の際、リシャードがなぜ1〜2sでできるのか? (1/5)
S S S S ノード = Spanner Servers2TB まで管理できるサーバ
Colossus (分散ストレージ )実データはここに格納される
C クライアント
Split
ノード数:4
各ノードは 複数の Split のオーナー
![Page 14: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/14.jpg)
ノード追加・削除の際、リシャードがなぜ1〜2sでできるのか? (2/5)
S S S S ノード = Spanner Servers
Colossus (分散ストレージ )
C クライアント
Split
ノード数:4>3
1ノードを削除
![Page 15: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/15.jpg)
ノード追加・削除の際、リシャードがなぜ1〜2sでできるのか? (3/5)
S S S ノード = Spanner Servers
Colossus (分散ストレージ )
C クライアント
Split
ノード数:31〜2秒後
Split のオーナーが変わるだけ
![Page 16: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/16.jpg)
ノード追加・削除の際、リシャードがなぜ1〜2sでできるのか? (4/5)
S S S S ノード = Spanner Servers
Colossus (分散ストレージ )
C クライアント
Split
ノード数:3>4
1ノードを追加
![Page 17: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/17.jpg)
ノード追加・削除の際、リシャードがなぜ1〜2sでできるのか? (5/5)
S S S S ノード = Spanner Servers
Colossus (分散ストレージ )
C クライアント
Split
ノード数:41〜2秒後
Split のオーナーがまた変わるだけ
![Page 18: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/18.jpg)
容量に関する上限(2GB and 2TB)
Cloud Spanner には 2TB size limit per node という容量上限があります。
インターリーブテーブルを使うと、裏上限がもう1つあります: 2GB per parent record and related child records
Max 2GB
![Page 19: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/19.jpg)
テーブルが分割(Split)されるロジック
Cloud Spanner は容量と負荷状況次第、テーブルを split します。ただし、実際にどのタイミングでテーブルが分割されるか
は保証できません。
Cloud Spanner では以下の2つの条件でテーブルが分割されます:
● Size-based splits○ テーブルの容量が数GB程度になったら、テーブルを split します
● Load-based splits○ Cloud Spanner は分散できる負荷だと、テーブルを split します。分散できない負荷は、 例えばシー
ケンシャルな INSERT(だから Hotspot が発生する)。
上記は、どれだけ PK の選択肢が重要かを示しています。
![Page 20: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/20.jpg)
負荷試験は十分長く実行する
Cloud Spanner の負荷試験を行う場合、5分ではなく、20〜30分の負荷試験をオススメします。その理由は、データの容量
が多くなることにより、Split がより多く発生して、データが正常に全ノード間に分散されるからです。
テーブルが十分 split されると、全ノードが
活用され、Cloud Spanner の最大の
パフォーマンスを出せるようになります。
Split happens
![Page 21: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/21.jpg)
負荷試験間はデータベースをDropする
負荷試験を毎回行う際は、Insert したデータを全て削除するのではなく、データベースを Drop するようオススメします。
データの削除+再Insert は、テーブルスキャンのパフォーマンスを劣化します。それは、削除されたデータは Garbage Collector が物理的に削除するまではテーブルに append されるからです。テーブルのクリーンアップまで1週間までかかり
ます。
Spanner のストレージは log-structured merge trees (LSM Tree)を使用している。 → Delete のオペレーションは "append a delete mutation" とストレージレベルで見られる。古いデータはデータベースがク
リーンアップされるまで削除されない。
→ 削除された PK がまだ格納されているので、テーブルスキャンがインパクトされる。
![Page 22: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/22.jpg)
TPSの数え方
パフォーマンスグラフは受信した API リクエスト数を表示する
● "reads/s" は read と query を含む
● "writes/s" はトランザクションのコミット数を示す その結果、TPS は "writes/s" ということになります 3 read API calls と 9 buffered mutations を含むトランザクションは 3R, 1W とカウントされる
![Page 23: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/23.jpg)
ノード数を縮小するについて
Cloud Spanner にはオートスケール機能はまだありません。
ノード数を縮小しようとすると、1ノードまでに縮小できない場合があります。
Spanner の仕組み上、Delete や Update されたデータは Garbage Collector が起動するまでに一時的に格納されます。そ
の理由は2つ:整合性のあるバックアップを行うためとより高いパフォーマンスを提供するためです(Cloud Spanner はデー
タ容量が多いほど、パフォーマンスが出るので)。
1
2
3
1. Monitor Spanner CPU usage
2. Trigger function when threshold hit
3. Function add a node
Autoscale workaround
![Page 24: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/24.jpg)
グラフの ”Total storage” の意味って?
Cloud Console のグラフとして表示される “Total storage” には最新のデータ+
削除・更新されたデータを含まれています。削除・更新されたデータは1週間以内
にクリーンアップされます(平均 3.5 日)。
古いデータを一時的に確保するメリットは:● 高スループットの Read/Write を提供するため
● 整合性のあるバックアップを取るため
お客様に課金されるデータ:
● ライブデータ
● 削除・更新されたデータ(1週間以内にクリーンアップされるまで)
![Page 25: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/25.jpg)
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();
これ重要!
![Page 26: 超実践 Cloud Spanner 設計講座](https://reader034.vdocuments.net/reader034/viewer/2022052116/5a6477587f8b9afc4d8b4757/html5/thumbnails/26.jpg)
Additional readings
● SQL Best Practices● Best Practices for Schema Design● Efficient Bulk Loading● Quizlet Cloud Spanner tests