主キーのデフォルト値の管理

このページでは、デフォルト値の式を使用してテーブル内の主キー値を生成する方法について説明します。これらの戦略には次のような利点があります。

  • ホットスポット化を防止する
  • 他のデータベースからの移行を簡素化する
  • キーロジックをデータベースにカプセル化し、アプリケーション内での管理について懸念する必要がないようにする

DEFAULT 式を含む列では、次の戦略を使用できます。

  • UUID バージョン 4 値を生成する UUID 関数。
  • bit_reversed_positive オプションを持つスキーマ オブジェクト SEQUENCESEQUENCE は GoogleSQL と PostgreSQL の両方で使用できます。

主キーを自動的に生成する方法

Universally Unique Identifier(UUID)

Spanner は、主キーとして使用する UUID バージョン 4 文字列を自動的に生成できます。UUID は、多数の行を持つ新しいアプリケーションとテーブルに適しています。これらはキー空間全体にほぼ均一に分散されるため、大規模なホットスポット化を防止できます。UUID の生成では非常に多くの値(2122)が生成され、各値は実質的に一意です。たとえば、50% の衝突確率では 2.71×1018、86 年間では 1 秒あたり 10 億が必要です。これにより、大規模なテーブルで使用するときに一意の値を確保します。UUID は、データベースで生成するかクライアントで生成するかにかかわらず、一意です。可能であれば、UUID を使用することをおすすめします。クライアントで生成された UUID が小文字としてシリアル化されている場合は、RFC 4122 に従って、クライアントで生成された UUID と Spanner で生成された UUID を安全に混在させることができます。

デフォルト値が必要な列の場合は、GENERATE_UUID 関数を使用して値を生成できます。次の例は、FanId キー列の値が GENERATE_UUID であるテーブルをデフォルト値として作成する方法を示しています。この例では、UUID が 36 文字であるため、Google SQL の STRING 属性と PostgreSQL varchar 属性には 36 文字を使用します。INSERT with THEN RETURN ステートメントを使用して Fans テーブルに挿入すると、GENERATE_UUID によって FanId の UUID 値が生成され、返されます。

GoogleSQL

CREATE TABLE Fans (
  FanId STRING(36) DEFAULT (GENERATE_UUID()),
  Name STRING(MAX),
) PRIMARY KEY (FanId);

PostgreSQL

CREATE TABLE Fans (
  FanId varchar(36) DEFAULT spanner.generate_uuid(),
  Name text,
  PRIMARY KEY (FanId)
);

GoogleSQL

INSERT INTO Fans (Name) VALUES ('Melissa Garcia')
THEN RETURN FanId;

PostgreSQL

INSERT INTO fans (name) VALUES ('Melissa Garcia')
RETURNING (fanid);

このステートメントで次のような結果が返されます。

FanId
6af91072-f009-4c15-8c42-ebe38ae83751

GENERATE_UUID() 関数の詳細については、GoogleSQL または PostgreSQL のリファレンス ページをご覧ください。

ビット反転シーケンス

ビット反転シーケンスは、整数のシーケンスを生成してビット反転するスキーマ オブジェクトです。このオブジェクトは、一意性を確保するために、プライベートな内部 Spanner カウンタでビット反転を使用します。生成されるビット反転値により、主キーで使用されるときに大規模なホットスポット化を回避できます。

Spanner では、bit_reversed_positive 属性とともに SEQUENCE DDL ステートメントを使用して、ビット反転した正の値(GoogleSQL、または PostgreSQL)を生成するシーケンスを作成、変更、または削除します。

各シーケンスは一連の内部カウンタを保持し、値を生成するために使用します。シーケンス カウンタは、ビット反転アルゴリズムへの入力を可能にします。

GoogleSQL GET-NEXT-SEQUENCE-VALUE 関数または PostgreSQL nextval 関数をデフォルト値として使用する DEFAULT 式を含む列を定義すると、Spanner は自動的に関数を呼び出し、ビット反転した出力値を列に入力します。ビット反転シーケンスは、主キーで特に活用できます。これは、ビット反転値は、キー空間全体に均等に分散されるため、ホットスポット化が発生しないためです。

次の例は、ビット反転シーケンスと、キー列がシーケンスをデフォルト値として使用するテーブルを作成する方法を示しています。

GoogleSQL

CREATE SEQUENCE SingerIdSequence OPTIONS (
  sequence_kind="bit_reversed_positive"
);

CREATE TABLE Singers (
  SingerId INT64 DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE SingerIdSequence)),
  Name STRING(MAX),
  Rank INT64,
) PRIMARY KEY (SingerId);

PostgreSQL

CREATE SEQUENCE SingerIdSequence bit_reversed_positive;

CREATE TABLE Singers (
  SingerId bigint DEFAULT nextval('SingerIdSequence'),
  Name text,
  PRIMARY KEY (SingerId)
);

主キーの値を挿入して返すには、次の SQL ステートメントを使用します。

GoogleSQL

INSERT INTO Singers (Name) VALUES ('Melissa Garcia')
THEN RETURN SingerId;

PostgreSQL

INSERT INTO Singers (name) VALUES ('Melissa Garcia')
RETURNING (SingerId);

このステートメントで次のような結果が返されます。

SingerId
3458764513820540928

主キーのデフォルト値として UUID とシーケンスを使用する場合のシナリオ

UUID とシーケンスのシナリオには、次のものがあります。

  • 新しいアプリケーション
  • 移行

以降のセクションでは、各シナリオについて説明します。

新しいアプリケーション

既存のアプリケーションで GoogleSQL の INT64 キーまたは PostgreSQL の bigint キーが必要な場合、Spanner はビット反転した正のシーケンス スキーマ オブジェクト(PostgreSQL または GoogleSQL)を提供します。それ以外の場合は、新しいアプリケーションで Universally Unique Identifier(UUID)を使用することをおすすめします。詳細については、Universally Unique Identifier(UUID)を使用するをご覧ください。

移行

Spanner へのテーブルの移行には、いくつかのオプションがあります。

  • ソース データベースで UUID を使用している場合、Spanner では STRING 型のキー列と GENERATE_UUID() 関数(GoogleSQL または PostgreSQL)をデフォルト値として使用できます。
  • 整数の主キーを使用しており、アプリケーションが一意のキーのみを必要とする場合は、INT64 でキー列を使用し、ビット反転した正のシーケンスを主キーのデフォルト値として使用できます。ビット反転キー列の移行をご覧ください。
  • Spanner は、単調な値を生成する方法をサポートしていません。

    PostgreSQL SERIAL タイプや MySQL AUTO_INCREMENT 属性などの単調なキーを使用しており、Spanner で新しい単調なキーが必要な場合は、複合キーを使用できます。キーの順序を入れ替える一意のキーをハッシュし、書き込みを論理シャードに分散するをご覧ください。

  • アプリケーションで GoogleSQL の INT64 キーまたは PostgreSQL の bigint キーを手動でビット反転する場合は、ビット反転した正のシーケンス(GoogleSQL またはPostgreSQL)を使用して、新しいキー値を生成できます。ビット反転キー列の移行をご覧ください。

次のステップ