本頁面說明如何將來源資料庫資料表的主鍵遷移至 Spanner GoogleSQL 方言資料庫和 PostgreSQL 方言資料庫。執行本頁面的程序之前,請先參閱「主鍵遷移總覽」。
事前準備
遷移自動產生的連續鍵
如果您要從使用單調遞增鍵的資料庫遷移,例如 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
型別,且大於零,但並非連續。
將現有資料列從來源資料庫遷移至 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。您可以設定 Spanner 序列,略過 [1, 21000]
範圍。額外 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 中使用外部產生的連續鍵,可以建立複合鍵,將均勻分布的值 (例如雜湊) 做為第一個元件,並將連續鍵做為第二個元件。這樣一來,您就能保留連續鍵值,而不會大規模建立熱點。請參考下列遷移工作流程:
假設您需要將具有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) );
遷移連續索引鍵資料欄
如果來源資料庫系統會為鍵欄產生連續值,您可以在 Spanner 結構定義中使用位元反轉的正序 (GoogleSQL、PostgreSQL),產生在正 64 位元整數數字空間中平均分配的值。為避免 Spanner 序列產生與遷移值重疊的值,您可以為該序列定義略過的範圍。
舉例來說,如果知道來源資料庫只會產生 32 位元整數,則可以為下列兩個序列略過 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;
遷移位元反轉金鑰資料欄
如果您已將鍵值位元反轉,避免來源資料庫發生熱點問題,也可以使用 Spanner 位元反轉正序 (GoogleSQL、PostgreSQL) 繼續產生這類值。為避免產生重複值,您可以設定序號,讓計數器從自訂數字開始。
舉例來說,如果您反轉 1 到 1000 的數字來產生主鍵值,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;