このページでは、ソース データベースのテーブルから Spanner GoogleSQL 言語データベースと PostgreSQL 言語データベースに主キーを移行する方法について説明します。このページの手順を実行する前に、主キーの移行の概要を確認してください。
始める前に
-
主キーを Spanner に移行するために必要な権限を取得するには、インスタンスに対する Cloud Spanner データベース管理者 (
roles/spanner.databaseAdmin
)IAM ロールを付与するよう管理者に依頼してください。
自動生成された連続するキーを移行する
MySQL の AUTO_INCREMENT
、PostgreSQL の SERIAL
、SQL Server または Oracle の標準 IDENTITY
型など、単調な連続するキーを使用するデータベースから移行する場合は、次の大まかな移行戦略を検討してください。
- Spanner で、整数の主キーを使用してソース データベースからテーブル構造を複製します。
- 連続する値を含む Spanner の列ごとに、シーケンスを作成し、
GET_NEXT_SEQUENCE_VALUE
(GoogleSQL、PostgreSQL)関数を列のデフォルト値として割り当てます。 - 元のキーを含む既存のデータをソース データベースから Spanner に移行します。Spanner 移行ツールまたは Dataflow テンプレートの使用を検討してください。
- 必要に応じて、任意の依存関係のテーブルに外部キー制約を設定できます。
- 新しいデータを挿入する前に、既存のキー値の範囲をスキップするように Spanner シーケンスを調整します。
- 新しいデータを挿入して、シーケンスが一意のキーを自動的に生成できるようにします。
移行ワークフローの例
次のコードは、SEQUENCE
オブジェクトを使用して Spanner でテーブル構造と関連するシーケンスを定義し、移行先テーブルのデフォルトのプライマリ値としてオブジェクトを設定します。
GoogleSQL
CREATE SEQUENCE singer_id_sequence OPTIONS ( SequenceKind = 'bit_reversed_positive' ); CREATE TABLE Singers ( SingerId INT64 DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE SingerIdSequence)), Name STRING(1024), Biography STRING(MAX), ) PRIMARY KEY (SingerId); CREATE TABLE Albums ( AlbumId INT64, SingerId INT64, AlbumName STRING(1024), SongList STRING(MAX), CONSTRAINT FK_singer_album FOREIGN KEY (SingerId) REFERENCES Singers (SingerId) ) PRIMARY KEY (AlbumId);
PostgreSQL
CREATE SEQUENCE SingerIdSequence BIT_REVERSED_POSITIVE; CREATE TABLE Singers ( SingerId BIGINT DEFAULT nextval('SingerIdSequence') PRIMARY KEY, Name VARCHAR(1024) NOT NULL, Biography TEXT ); CREATE TABLE Albums ( AlbumId BIGINT PRIMARY KEY, SingerId BIGINT, AlbumName VARCHAR(1024), SongList TEXT, CONSTRAINT FK_singer_album FOREIGN KEY (SingerId) REFERENCES Singers (SingerId) );
bit_reversed_positive
オプションは、シーケンスによって生成される値が INT64
型で、0 より大きく、連続していないことを示します。
既存の行をソース データベースから Spanner に移行する際、主キーは変更されません。
新しい挿入で主キーを指定しない場合、Spanner は自動的に GET_NEXT_SEQUENCE_VALUE
(GoogleSQL または PostgreSQL)関数を呼び出して新しい値を取得します。
これらの値は [1, 263]
の範囲に均等に分散されるため、既存のキーとの競合が発生する可能性があります。これを防ぐには、ALTER_SEQUENCE
(GoogleSQL または PostgreSQL)を使用してシーケンスを構成し、既存のキーでカバーされている値の範囲をスキップします。
singers
テーブルが PostgreSQL から移行され、その主キー singer_id
が SERIAL
型であるとします。次の PostgreSQL は、ソース データベースの DDL を示しています。
PostgreSQL
CREATE TABLE Singers ( SingerId SERIAL PRIMARY KEY, Name varchar(1024), Biography varchar );
主キー値は単調に増加します。移行後、Spanner で主キー singer_id
の最大値を取得できます。Spanner で、次のコードを使用します。
GoogleSQL
SELECT MAX(SingerId) FROM Singers;
PostgreSQL
SELECT MAX(SingerId) FROM Singers;
返された値が 20,000 だったとしましょう。[1, 21000]
の範囲をスキップするように Spanner のシーケンスを構成できます。余分な 1,000 は、最初の移行後のソース データベースへの書き込みに対応するためのバッファとして機能します。Spanner で生成された新しいキーは、ソース PostgreSQL データベースで生成された主キーの範囲と競合しません。Spanner で、次のコードを使用します。
GoogleSQL
ALTER SEQUENCE SingerIdSequence SET OPTIONS ( skip_range_min = 1, skip_range_max = 21000 );
PostgreSQL
ALTER SEQUENCE SingerIdSequence SKIP RANGE 1 21000;
Spanner とソース データベースを使用する
範囲スキップのコンセプトを使用すると、Spanner またはソース データベースのいずれかが主キーを生成するシナリオをサポートできます。たとえば、移行のカットオーバー時にどちらかの方向にレプリケーションを有効にし、障害復旧を確保するといったことが可能です。
これをサポートするために、両方のデータベースで主キーが生成され、データが両データベース間で同期されます。重複しないキー範囲に主キーを作成するように各データベースを構成できます。ソース データベースの範囲を定義するときに、その範囲をスキップするように Spanner シーケンスを構成できます。
たとえば、音楽トラック アプリケーションの移行後に、PostgreSQL から Spanner にデータを複製して、カットオーバーにかかる時間を短縮します。
Spanner でアプリケーションを更新してテストした後に、ソース PostgreSQL データベースの使用を停止し、Spanner を使用して更新と新しい主キーの記録システムにすることができます。Spanner が引き継ぐと、データベース間のデータのフローを PostgreSQL インスタンスに逆転できます。
ソース PostgreSQL データベースで SERIAL
主キー(32 ビットの符号付き整数)を使用しているとします。Spanner の主キーはそれより大きい 64 ビットの数値です。PostgreSQL で、主キー列を 64 ビット列または bigint
に変更します。ソース PostgreSQL データベースで次のコードを使用します。
PostgreSQL
ALTER TABLE Singers ALTER COLUMN SingerId TYPE bigint;
ソース PostgreSQL データベースのテーブルに CHECK
制約を設定し、SingerId
主キーの値が常に 231-1
以下になるようにします。
ソース PostgreSQL データベースで次のコードを使用します。
PostgreSQL
ALTER TABLE Singers ADD CHECK (SingerId <= 2147483647);
Spanner では、[1, 231-1]
範囲をスキップするようにシーケンスを変更できます。
Spanner で、次のコードを使用します。
GoogleSQL
ALTER SEQUENCE SingerIdSequence SET OPTIONS (
skip_range_min = 1,
skip_range_max = 2147483647 -- 231-1
);
PostgreSQL
ALTER SEQUENCE SingerIdSequence SKIP RANGE 1 2147483648;
ソース PostgreSQL データベースは常に 32 ビットの整数空間にキーを生成しますが、Spanner キーは 64 ビットの整数空間に制限され、すべての 32 ビットの整数値より大きくなります。これにより、両方のデータベースが競合しない主キーを独立して生成できます。
UUID キー列を移行する
UUIDv4 キーは、生成される場所に関係なくほぼ一意になります。他の場所で生成された UUID キーは、Spanner で生成された新しい UUID キーと統合されます。
UUID キーを Spanner に移行するための大まかな戦略は次のとおりです。
- デフォルトの式で文字列の列を使用して、Spanner で UUID キーを定義します。
GENERATE_UUID()
関数を使用します(GoogleSQL、PostgreSQL)。 - ソースシステムからデータをエクスポートして、UUID キーを文字列としてシリアル化します。
- 主キーを Spanner にインポートします。
- 省略可: 外部キーを有効にします。
移行ワークフローの例を次に示します。
Spanner で、UUID 主キーの列を STRING
型または TEXT
型として定義し、そのデフォルト値として GENERATE_UUID()
(GoogleSQL または PostgreSQL)を割り当てます。ソース データベースから Spanner にすべてのデータを移行します。移行後、新しい行が挿入されると、Spanner は GENERATE_UUID()
を呼び出して主キーの新しい UUID 値を生成します。たとえば、テーブル FanClubs
に新しい行が挿入されると、主キー FanClubId
は UUIDv4 値を取得します。Spanner で、次のコードを使用します。
GoogleSQL
CREATE TABLE Fanclubs ( FanClubId STRING(36) DEFAULT (GENERATE_UUID()), ClubName STRING(1024), ) PRIMARY KEY (FanClubId); INSERT INTO FanClubs (ClubName) VALUES ("SwiftFanClub");
PostgreSQL
CREATE TABLE FanClubs ( FanClubId TEXT DEFAULT spanner.generate_uuid() PRIMARY KEY, ClubName VARCHAR(1024) ); INSERT INTO FanClubs (ClubName) VALUES ('SwiftFanClub');
独自の主キーを移行する
アプリケーションが主キーの順序に基づいて、データの更新頻度を判断したり、新しく作成されたデータをシーケンス化したりしている可能性があります。外部で生成された連続するキーを Spanner で使用するには、ハッシュなどの均等に分散された値を最初のコンポーネントとして、連続するキーを 2 番目のコンポーネントとして組み合わせる複合キーを作成します。これにより、大規模なホットスポットを作成することなく、連続するキー値を保持できます。次の移行ワークフローを検討してください。
AUTO_INCREMENT
主キーを使用した MySQL テーブルである students
を Spanner に移行する必要がある場合を考えてみましょう。ソース MySQL データベースで次のコードを使用します。
MySQL
CREATE TABLE Students ( StudentId INT NOT NULL AUTO_INCREMENT, Info VARCHAR(2048), PRIMARY KEY (StudentId) );
Spanner では、StudentId
列のハッシュを作成することで、生成列 StudentIdHash
を追加できます。例:
StudentIdHash = FARM_FINGERPRINT(CAST(StudentId AS STRING))
Spanner で次のコードを使用できます。
GoogleSQL
CREATE TABLE student ( StudentIdHash INT64 AS (FARM_FINGERPRINT(cast(StudentId as string))) STORED, StudentId INT64 NOT NULL, Info STRING(2048), ) PRIMARY KEY(StudentIdHash, StudentId);
PostgreSQL
CREATE TABLE Student ( StudentIdHash bigint GENERATED ALWAYS AS (FARM_FINGERPRINT(cast(StudentId AS varchar))) STORED, StudentId bigint NOT NULL, Info varchar(2048), PRIMARY KEY (StudentIdHash, StudentId) );
連続するキー列を移行する
ソース データベース システムがキー列の連続値を生成する場合は、Cloud Spanner スキーマ内でビット反転した正のシーケンス(GoogleSQL、PostgreSQL)を使用して、64 ビットの正の整数空間に均等に分散する値を生成できます。Spanner シーケンスで移行された値と重複する値が生成されないようにするには、スキップする範囲を定義します。
たとえば、ソース データベースが 32 ビット整数のみを生成していることがわかっている場合は、次の 2 つのシーケンスで 1~4,294,967,296(2^32)の範囲をスキップできます。
GoogleSQL
CREATE SEQUENCE MyFirstSequence OPTIONS ( sequence_kind = "bit_reversed_positive", skip_range_min = 1, skip_range_max = 4294967296 ); ALTER SEQUENCE MySecondSequence SET OPTIONS ( skip_range_min = 1, skip_range_max = 4294967296 );
PostgreSQL
CREATE SEQUENCE MyFirstSequence BIT_REVERSED_POSITIVE SKIP RANGE 1 4294967296; ALTER SEQUENCE MySecondSequence SKIP RANGE 1 4294967296;
IDENTITY
列を使用してキー列の整数値を自動生成する場合は、スキップ範囲を設定できます。
GoogleSQL
スキップ範囲を設定するには、GENERATED BY DEFAULT AS IDENTITY
コマンドを使用します。
ALTER DATABASE db SET OPTIONS (
default_sequence_kind = 'bit_reversed_positive',
);
CREATE TABLE MyFirstTable (
Id INT64 GENERATED BY DEFAULT AS IDENTITY (SKIP RANGE 1, 4294967296),
Name STRING(MAX),
) PRIMARY KEY (Id);
ALTER TABLE MyFirstTable ALTER COLUMN Id ALTER IDENTITY SET SKIP RANGE 1, 4294967296;
PostgreSQL
スキップ範囲を設定するには、GENERATED BY DEFAULT AS IDENTITY
コマンドを使用します。
ALTER DATABASE db
SET spanner.default_sequence_kind = 'bit_reversed_positive';
CREATE TABLE MyFirstTable (
Id bigint GENERATED BY DEFAULT AS IDENTITY (SKIP RANGE 1 4294967296),
Name text,
PRIMARY KEY (Id)
);
ALTER TABLE MyFirstTable ALTER COLUMN Id SET SKIP RANGE 1 4294967296;
ビット反転キー列を移行する
ソース データベースでのホットスポットの問題を回避するため、すでにキーの値をビット反転している場合は、Cloud Spanner のビット反転した正のシーケンス(GoogleSQL、PostgreSQL)を使用して、引き続きそれらの値を生成することもできます。重複値の生成を回避するため、カスタム数値からカウンタを開始するようにシーケンスを構成できます。
たとえば、1~1,000 の数値を逆にして主キー値を生成した場合、Spanner シーケンスは 10,000 より大きい任意の数値からカウンタを開始できます。必要に応じて、大きな数値を選択し、データ移行後にソース データベースで発生した新しい書き込みに対してバッファを残すことができます。次の例では、カウンタは 11,000 から開始されます。
GoogleSQL
CREATE SEQUENCE MyFirstSequence OPTIONS ( sequence_kind = "bit_reversed_positive", start_with_counter = 11000 ); ALTER SEQUENCE MySecondSequence SET OPTIONS ( start_with_counter = 11000 );
PostgreSQL
CREATE SEQUENCE MyFirstSequence BIT_REVERSED_POSITIVE START COUNTER 11000; ALTER SEQUENCE MySecondSequence RESTART COUNTER 11000;
IDENTITY
列を使用してキー列の整数値を自動的に生成する場合は、開始カウンタを設定できます。
GoogleSQL
開始カウンタを設定するには、GENERATED BY DEFAULT AS IDENTITY
コマンドを使用します。
ALTER DATABASE db SET OPTIONS (
default_sequence_kind = 'bit_reversed_positive',
);
CREATE TABLE MyFirstTable (
Id INT64 GENERATED BY DEFAULT AS IDENTITY (START COUNTER WITH 11000),
Name STRING(MAX),
) PRIMARY KEY (Id);
ALTER TABLE MyFirstTable ALTER COLUMN Id ALTER IDENTITY RESTART COUNTER WITH 11000;
PostgreSQL
開始カウンタを設定するには、GENERATED BY DEFAULT AS IDENTITY
コマンドを使用します。
ALTER DATABASE db
SET spanner.default_sequence_kind = 'bit_reversed_positive';
CREATE TABLE MyFirstTable (
Id bigint GENERATED BY DEFAULT AS IDENTITY (START COUNTER WITH 11000),
Name text,
PRIMARY KEY (Id)
);
ALTER TABLE MyFirstTable ALTER COLUMN Id RESTART COUNTER WITH 11000;