Slide 1

Slide 1 text

Google Cloud Spannerの 基礎知識 Unipos株式会社 バックエンドエンジニア 周東 拓哉 @Gunma.web #49

Slide 2

Slide 2 text

⾃⼰紹介 周東 拓哉(しゅうとう たくや) - エンジニア3年⽬ - 前橋市出⾝ - 群⾺⾼専通ってました IPAマニアになりつつある AP・DB・SC → 次はPM! Unipos株式会社 - バックエンドエンジニア(役職) Scala・Go・SQLを書いて⽣活してます ・NoSQLからNewSQLへのDB移⾏を担当 ・Cloud Spannerが⼤好きです 最近社内ハッカソン優勝しました UniposのAI投稿シミュレータ 1

Slide 3

Slide 3 text

Cloud Spannerの特徴 リレーショナルデータベース 分散データベース(NewSQL) × ・SQL ・関係スキーマ ・正規化 ・ACID特性 ・⽔平スケール ・CAP定理の克服 ・強整合性の実現 ・99.99%のSLA ・スプリットによるデータ分散 通常のRDBとは異なるハマりどころがあり、初⾒ではパフォーマンスチューニングが難しい 特に、データアクセス・結合の仕組みを意識しないと使いこなすことが難しい 2

Slide 4

Slide 4 text

前提知識 3

Slide 5

Slide 5 text

前提知識: 分散化と冗⻑化 分散DBのスプリットはストライピングとミラーリングを応⽤している 4

Slide 6

Slide 6 text

スプリットとは テーブルに格納されるデータは、 主キーの範囲ごとにスプリットへ (ストライピング) Zone⽅向にミラーリングする 5

Slide 7

Slide 7 text

スプリット分散 SplitはNodeとZoneの両⽅に 分散化・冗⻑化している さらにリージョンを跨いで 分散化・冗⻑化も可能 6

Slide 8

Slide 8 text

テーブル設計 7

Slide 9

Slide 9 text

ホットスポット UserAccessLog(LastAccess, UserId, …) ×単調増加するキーが主キーの先頭 保存されるスプリットはキーの範囲で決定 https://cloud.google.com/spanner/docs/schema-design?hl=ja [1230219000000000, 001930]までのデータ → スプリットAへ格納 [1230219000001000, 001519]からのデータ → スプリットBへ格納 同時に追加されるデータの書き込みが特定のスプリットへ集中し、ホットスポットが発⽣ → 書き込み性能の低下・コンピューティングリソースの占有 8

Slide 10

Slide 10 text

主キー設計: ホットスポットの回避 UserAccessLog(UserId, LastAccess, …) ◯ ランダムな値が主キーの先頭 キー範囲がランダムに格納先スプリットが分散 推奨される対策 ・UUIDv4を主キーに利⽤ ・ShardIdを主キーの先頭に付与 ・ShardId = hash(LastAccess and UserId) % N → N個の論理シャードに分割する https://cloud.google.com/spanner/docs/schema-design?hl=ja 9

Slide 11

Slide 11 text

索引設計: 分散結合の発⽣ インデックス MemberByDepartmentID ベーステーブル Member SELECT ID, Name, EmailAddress FROM Member@{FORCE_INDEX=MemberByDepartmentID} CREATE INDEX MemberByDepartmentID ON Member(DepartmentID); 部署IDでメンバーを検索するための索引 ⽇本 ブラジル Spannerは世界規模の分散DBで、 データセンタ間の物理的な距離が遠い ケースもある Hit! Hit! Hit! → 遠隔地のデータを伝送・結合する処理が発⽣ dept01 dept01 dept01 dept02 dept02 dept02 索引検索後, 対応する主キーを持つレコードから Name, EmailAddressを引こうとする。 10

Slide 12

Slide 12 text

索引設計: STORINGによる分散結合対策 SELECT ID, Name, EmailAddress, FROM Member@{FORCE_INDEX=MemberByDepartmentID} CREATE INDEX MemberByDepartmentID ON Member(DepartmentID) STORING (Name, EmailAddress); 索引にクエリ時に⼀緒に取得したいカラムを格納できる Hit! Hit! Hit! STORINGは索引の並び順に影響を与えない インデックス MemberByDepartmentID dept01 dept01 dept01 dept02 dept02 dept02 STORING KEY TANAKA, … YAMADA, … NONAKA, … SATOU, … NOJIMA, … KOJIMA, … 分散結合を回避できるため、クエリが⾼速になる 11

Slide 13

Slide 13 text

テーブル設計: INTERLEAVE テーブル間の親⼦関係を表現するにはINTERLEAVE → 外部キー制約との選択 INTERLEAVEの特徴 ・親⼦を物理的に⼀緒に格納する ・DELETE CASCADEを使える 同時に取得・削除するようなテーブルに利⽤ https://cloud.google.com/spanner/docs/schema-and-data-model?hl=ja 12

Slide 14

Slide 14 text

テーブル設計: INTERLEAVE CREATE TABLE Singers( SingerId INT64 NOT NULL, FirstName STRING(256), LastName STRING(256), SingerInfo BYTES(MAX), ) PRIMARY KEY (SingerId); CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(256), ) PRIMARY KEY (SingerId, AlbumId), INTERLEAVE IN PARENT Singers ON DELETE CASCADE; SELECT s.*, ARRAY( SELECT AS STRUCT a.* FROM Albums a WHERE a.SingerId = s.SingerId ) Albums, FROM Singers s WHERE s.SingerId = @SingerId 物理的に⼀緒に格納 ⼀緒に取得する場合、JOINコストがなく⾼速 https://cloud.google.com/spanner/docs/schema-and-data-model?hl=ja ARRAY(サブクエリで取得) 13

Slide 15

Slide 15 text

まとめ • Cloud Spannerはリレーショナルな分散DB • ホットスポットは主キーの先頭をランダムにして回避すべし • 分散結合はSTORINGで回避すべし • 同時に取得・削除するならINTERLEAVE 14

Slide 16

Slide 16 text

今⽇の内容は記事にもしているので、よければ是⾮! Cloud Spannerのスプリット分散をわかった気になる Cloud Spannerのパフォーマンスチューニングの勘所 15 クエリチューニングの話題は今回省いたので、記事をどうぞ! Thank you!