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

このページでは、デフォルト値の式を使用してテーブル内の主キー値を生成する方法について説明します。このページの情報は、GoogleSQL 言語データベースと PostgreSQL 言語データベースの両方に適用されます。これらの戦略には次のようなメリットがあります。

  • ホットスポットを回避する
  • 他のデータベースからの移行を簡素化する
  • キーロジックをデータベースにカプセル化し、アプリケーション内での管理について懸念する必要がないようにする
  • ほとんどの場合、独自のシーケンスを作成して管理する必要がなくなります

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

主キー値を自動生成するには、DEFAULT 式を含む列で次の戦略を使用します。

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

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

このセクションでは、主キー値として使用する UUID とビット反転シーケンスを自動的に生成する方法について説明します。

Universally Unique Identifier(UUID)

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

デフォルト値が必要な列の場合は、GENERATE_UUID 関数を使用してデフォルト値を生成できます。次の例は、FanId キー列の値列のデフォルト値として GENERATE_UUID を持つテーブルを作成する方法を示しています。この例では、UUID が 36 文字であるため、GoogleSQL の STRING 属性と PostgreSQL の varchar 属性に 36 文字を使用しています。INSERT with THEN RETURN ステートメントを使用して Fans テーブルに挿入すると、GENERATE_UUIDFanId の 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 のリファレンス ページをご覧ください。

IDENTITY

IDENTITY 列を使用すると、キー列と非キー列の整数値を自動的に生成できます。IDENTITY 列では、ユーザーが基盤となるシーケンスを手動で維持したり、列と基盤となるシーケンスの関係を管理する必要はありません。自動生成された ID 列が削除されると、基盤となるシーケンスも自動的に削除されます。

IDENTITY 列を使用するには、シーケンスの生成時に開始の整数値を指定する方法と、Spanner に整数シーケンスを生成させる方法があります。開始の整数値を指定するには、START COUNTER WITH オプションを使用して、正の INT64 開始値を使用する必要があります。Spanner は、この値を使用して自動生成された内部シーケンス カウンタの次の値を設定し、この列に挿入する前に値をビット反転します。

Spanner では、IDENTITY 列は GoogleSQL と PostgreSQL の両方でサポートされています。

GoogleSQL

次の例は、CREATE TABLE コマンドを使用して新しいテーブルを作成するときに、IDENTITY 列を使用して SingerId の自動生成整数の主キー列を作成する方法を示しています。

CREATE TABLE Singers (
  SingerId INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE),
  Name STRING(MAX),
  Rank INT64
) PRIMARY KEY (SingerId);

START_WITH_COUNTER オプションを使用して、列のカウンタの開始を指定することもできます。次の例では、ビット反転された正の値と 1,000 から始まる内部カウンタを持つ SingerId に、自動生成された整数列が作成されます。

CREATE TABLE Singers (
  SingerId INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000),
  Name STRING(MAX),
  Rank INT64
) PRIMARY KEY (SingerId);

PostgreSQL

次の例は、CREATE TABLE コマンドを使用して新しいテーブルを作成するときに、IDENTITY 列を使用して SingerId の自動生成整数列を作成する方法を示しています。

CREATE TABLE Singers (
  SingerId bigint GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE),
  Name text,
  PRIMARY KEY (SingerId)
);

START COUNTER WITH オプションを使用して、列のカウンタの開始を指定することもできます。次の例では、ビット反転された正の値を生成する SingerId に自動生成された整数列が作成されます。ビット反転前の内部カウンタは 1,000 から開始されます。

CREATE TABLE Singers (
  SingerId bigint GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000),
  Name text,
  PRIMARY KEY (SingerId)
);

SERIAL と AUTO_INCREMENT

Spanner は、PostgreSQL の SERIAL と GoogleSQL の AUTO_INCREMENT をサポートしています。これらは IDENTITY 列の DDL エイリアスであり、一意の整数列の作成に使用されます。SERIAL または AUTO_INCREMENT を使用する前に、まずデータベースの default_sequence_kind オプションを設定する必要があります。次の SQL ステートメントを使用して、データベースの default_squence_kind オプションを設定できます。

GoogleSQL

ALTER DATABASE db SET OPTIONS (default_sequence_kind = 'bit_reversed_positive');

CREATE TABLE Singers (
  id INT64 AUTO_INCREMENT PRIMARY KEY,
  name STRING(MAX),
)

PostgreSQL

ALTER DATABASE db SET spanner.default_sequence_kind = 'bit_reversed_positive';

CREATE TABLE Singers (
  id serial PRIMARY KEY,
  name text
);

SERIALAUTO_INCREMENT は IDENTITY 列にマッピングされるため、スキーマをシリアル化するときには表示されません。このスキーマの場合、GetDatabaseDDL の出力は次のようになります。

GoogleSQL

ALTER DATABASE db SET OPTIONS (default_sequence_kind = 'bit_reversed_positive');

CREATE TABLE Singers (
  id INT64 GENERATED BY DEFAULT AS IDENTITY,
  name STRING(MAX),
) PRIMARY KEY (id);

PostgreSQL

ALTER DATABASE db SET spanner.default_sequence_kind = 'bit_reversed_positive';

CREATE TABLE Singers (
  id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL,
  name character varying,
  PRIMARY KEY(id)
);

ビット反転シーケンス

ビット反転シーケンスは、整数のシーケンスを生成してビット反転するスキーマ オブジェクトです。このオブジェクトは、一意であることを保証するために、非公開の内部 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)を使用して、新しいキー値を生成できます。詳細については、ビット反転キー列の移行をご覧ください。

次のステップ