コンテンツに移動
データベース

Cloud Spanner の自動生成キーで大規模化状況でのベスト プラクティスを簡素化

2023年9月11日
https://storage.googleapis.com/gweb-cloudblog-publish/images/DB_next.max-2500x2500.jpg
Google Cloud Japan Team

※この投稿は米国時間 2023 年 8 月 31 日に、Google Cloud blog に投稿されたものの抄訳です。

金融サービス、ゲーム、小売など多くの業界の先進的なお客様が Cloud Spanner を使用して、ダウンタイムのないスケーリングが必要な要件の厳しいリレーショナル データベースのワークロードに対応しています。Google の分散インフラストラクチャ上に構築された Spanner は、あらゆるスケールにおいて最高レベルの整合性と可用性を備えたフルマネージド エクスペリエンスを提供します。

開発者のニーズに応えるための継続的な取り組みの一環として、本日の Google Cloud Next では Spanner での自動生成キーのサポートについて発表しました。自動生成キーを使用すると、スキーマ作成者は重要な ID ロジックをデータベースに任せることができます。これにより、アプリケーション コードが簡素化され、エラーや不整合が発生する可能性が減ります。また、自動生成キーは、キーが整数シーケンスに基づくことを前提とするリレーショナル データベースからの移行にも役立ちます。Spanner のすべての機能と同様に、自動生成キーは、アプリケーションのライフサイクル全体にわたってスケーラビリティと可用性、パフォーマンスが損なわれないようにゼロから設計されています。

具体的な機能

次の機能が自動生成キーの基礎となっています。

  • 主キーのデフォルト値: INSERT で指定されない場合に、テーブルの DEFAULT 主キー値を計算する式を DDL に指定します。DML クエリで RETURNING(PostgreSQL)句または THEN RETURN(GoogleSQL)句を使用して、新しく作成された値を取得できます。

  • UUID 機能: テーブルの主キーの DEFAULT 式の一部として UUID(v4)を生成します。

  • 整数シーケンス(ビット反転): 主キーの DEFAULT 式の一部として、均等に分散された一意の数値を生成します。

  • 主キー生成列: 増加する数値やタイムスタンプ値をハッシュしてホットスポット化を回避するなどの目的で、複合主キーのコンポーネントを生成します。

  • ビット反転機能: ホットスポット化を回避するために、ビット反転シーケンスと同じロジックを使用して既存の整数キーをマッピングします。

これらの機能が連携して、以前のデータベースにおけるデフォルトのキーおよびシーケンスのユーザビリティと、大規模化状況での Spanner のベスト プラクティスのバランスを取ります。これらはすべて、現在、PostgreSQL と GoogleSQL の両方の言語で利用できます。

1 つずつ数えることは実は難しい

ほとんどのリレーショナル データベースにおいて、整数シーケンスまたは自動インクリメント型を使用してサロゲートキーを作成することが、主キーのデフォルトの指針となっています。ボリュームが小さい単一インスタンスのデータベースでは、単調に増加するキーは理解しやすく、パフォーマンスも良好です。

ただし、規模が大きくなると、効率的に 1 つずつ数えることが驚くほど困難になります。ステップごとに 1 つずつ増える真に単調なシーケンスを実現するには、カウンタをグローバルにロックすることが必要です。そのため、人気店の行列と同様に、トランザクションが番号を待つことでレイテンシが増える可能性があります。また、これによって単一障害点が発生する可能性もあります。単一インスタンスのリレーショナル データベースであっても、シーケンスのシャーディングやキャッシュなどのオプションが追加され、パフォーマンスや可用性が高まることと引き換えに、1 つずつ数える単純さが損なわれます。

スケールアップからスケールアウトまで

Spanner のように大きく分散されたシステムでは、順序付けられたキーを使用することにより、大規模化状況で「ホットスポット化」が発生する可能性もあります。

Spanner は範囲シャーディングを使用して、スプリットと呼ばれる行のグループを Spanner インスタンス内のコンピューティング リソース全体に分散します。このことによってデータベースがクエリと更新を同時に処理できるようになり、それが Spanner のスケーリングの仕組みの基礎となっています。範囲シャーディングでは主キーによる並べ替え順に行が配置されるため、同じ範囲の値での挿入や更新は同じスプリットに入る傾向があります。Spanner の自動スプリットと再バランスの処理が負荷に対応できないと、利用可能なコンピューティング リソースとメモリリソースが「ホット」スプリットによって使い果たされることがあります。このようなことが起こると、Spanner の作業スケジューラがキューに入れるリクエストがさらに増え、レイテンシが増加し、タイムアウトやトランザクションの中止につながる可能性があります。

そのため、Spanner が作業を均等に分散できるように主キーを選択することが非常に重要です。関連性のない、ほぼ同時に発生するすべての挿入が、同じスプリットをターゲットにしないようにする必要があります。

Spanner の範囲パーティショニングのベスト プラクティスと開発者のエクスペリエンスを考慮し、Cloud Spanner に、データベース内で主キーを生成する 2 つの新しい方法、UUID と整数シーケンスが導入されました。

Universally Unique Identifier(UUID)

Spanner ではデフォルトで主キーに Universally Unique Identifier(UUID)を使用することをおすすめしています。UUID は、公開されている仕様(RFC 4122)を使用して生成される 128 ビットの識別子です。この仕様のバージョン 4 では 122 ビットのランダムデータが要求され、その結果として値がほぼ均等に分散されるため、Spanner のキーでホットスポット化を避けるための適切な候補となります。122 ビットが使用されることで、およそ 5×1036 という非常に多くの数の値が可能になります。

範囲の広さとランダム性により、UUID がどこで生成されるかに関係なく、実質的に一意性が確保されます。現在、多くの Spanner のお客様がアプリケーションで UUID の主キーを生成しています。このリリースでは、データベース内に UUID を生成するデフォルトの式を DDL で指定することもできるため、柔軟性がさらに高まっています。たとえば、大規模な一括挿入では、上流プロセスにおいて外部で主キーが生成される場合があります。ただし、同じデータベースを参照する対話型アプリケーションでデフォルトの生成にフォールバックして、すべて確実に同じロジックを使用するようにできます。

テーブルで PostgreSQL または GoogleSQL 言語のデータベースの新しい GENERATE_UUID() 関数を主キーのデフォルト値式で使用して、新しい行に UUID v4 値を自動的に入力できます。

PostgreSQL 構文では、デフォルトの UUID 主キーを持つ Spanner テーブルは次のようになります。


読み込んでいます...

現在、UUID は文字列表現を使用して Spanner に保存されます。一般的に、文字列を使用すると入出力が簡単なため、よりコンパクトになる可能性があるバイト表現よりも扱いやすくなります。そのため、PostgreSQL の名前空間を使用する spanner.generate_uuid() 関数はテキストを返します。

GoogleSQL で RETURNING(または THEN RETURN)を使用して、データベースが作成した主キーの値を取得できます。
読み込んでいます...

整数シーケンス

スキーマを最初から設計する場合は UUID が最も簡単です。アプリケーション、ツール、または既存のスキーマで整数の主キーが使用されている場合はどうでしょうか。

Spanner では主キーの DEFAULT 式の一部として一意の整数を生成する SEQUENCE オブジェクトが提供されるようになりました。ただし、単調なシーケンスとは異なり、Spanner シーケンスによって生成される値は均等に分散されるため、大規模化状況でのホットスポット化は発生しません。これは他のデータベースでのシーケンスに最初から備わっている動作ではありませんが、デフォルトの整数キーを想定する重要なアプリケーションやスキーマ ロジックを大幅に変更することなく、大規模化状況での一意性とパフォーマンス、可用性という重要な要件に対処します。

Spanner では他のリレーショナル データベースの場合と同様にシーケンスを宣言します。PostgreSQL では nextval() 関数、GoogleSQL では GET_NEXT_SEQUENCE_VALUE() を使用して、デフォルトの式でそのシーケンスから値を生成できます。

たとえば、Spanner の PostgreSQL 言語を使用すると、次のようになります。

読み込んでいます...

現在は bit_reversed_positive オプション(GoogleSQL では sequence_kind='bit_reversed_positive')が必須です。ビット反転シーケンスは、基礎となる計数メカニズムを取得して変換を適用して返し、カウンタの現在値のバイナリ表現内のバイト順序を変更します。その結果、データベース内で自動的に一意の整数が生成されますが、それは 1 から始まる単純な増分値ではありません。ビット反転シーケンスによってすべての正の整数にわたって値が分散されることで、大規模化状況でのホットスポット化が回避されます。

読み込んでいます...

シーケンスは高可用性を実現するために内部的に複数のカウンタを使用しますが、開発者はこの特定の実装に依存しないようにする必要があります。このアプローチは将来のリリースで変更される可能性があります。Spanner のシーケンスは、カウンタというよりも乱数ジェネレーターのように扱うことが適切です。行が挿入される順序を追跡する必要があるアプリケーションでは、ID と順序の側面を切り離すために別個のタイムスタンプ列を作成する必要があります。タイムスタンプのインデックス作成に関する追加のガイダンスをご覧ください。

主キー戦略の選択

アプリケーションの柔軟性と相互運用性を最大化するには、通常、UUID キーを選ぶことが最善です。シーケンスは既存のスキーマまたはアプリケーション コードの移行に適しています。デフォルト値にシーケンスキーを使用すると、挿入時にわずかなオーバーヘッド(通常、調整と定期的なキャッシュのリフレッシュに 100 μs 未満)が発生します。それでも、この 1 回限りのわずかな処理負担により、大規模化状況での一意性が保証されるという利点が得られます。

今すぐ使用を開始する

このたび、Google Cloud は、ユーザーがすでに知っている SQL のコンセプトを使用して Spanner の主キーのベスト プラクティスを実装するために役立つ新機能を導入しました。ユーザーは、UUID または整数シーケンスを主キーのデフォルト値として使用できるようになりました。これらは大規模化状況でのパフォーマンスと可用性を実現できるように設計され、アプリケーション コードを簡素化するための柔軟性を提供します。

次回の投稿では、自動インクリメント キーを使用するデータベースからのスキーマとデータの移行について詳しく説明します。今後の情報にご注目ください。

それまでの間、Spanner の独自性や使用例の詳細をご覧ください。または、90 日間無料で、あるいは月額わずか 65 米ドルで、中断を伴う再構築やダウンタイムなしでビジネスの成長に合わせて拡張できる本番環境対応のインスタンスを実際にお試しください。


- ソフトウェア エンジニア Diem Tran
- ソフトウェア エンジニア Sean Fox

投稿先