迁移主键策略

本文档介绍了从数据库迁移主键的策略 导出到 Spanner,以避免热点问题。热点是指 集中在单个节点上执行操作,这会降低写入吞吐量 而不是从对所有写入操作进行负载均衡中受益 Spanner 节点之间分配负载。使用单调递增或递减 减少列作为主键的第一部分(例如 常规序列或时间戳)是出现热点的最常见原因。

整体策略

在 Spanner 中,必须存储多行的每个表都必须 具有由表的一个或多个列组成的主键。您的表 主键唯一标识表中的每一行,以及 Spanner 使用主键对表格中的行进行排序。由于 Spanner 因此您可以使用以下方法生成唯一 并降低出现热点的风险:

  • 使用 Spanner 自动生成的针对热点的关键功能 (有关详情,请参阅迁移自动生成的 keys): <ph type="x-smartling-placeholder">
      </ph>
    • 使用 GENERATE_UUID() 函数(GoogleSQLPostgreSQL) 生成通用唯一标识符(UUID 版本 4)值, STRING(36) 数据类型。RFC 4122 定义了 UUID 版本 4 格式。
    • 使用位反转正序列(GoogleSQLPostgreSQL)。 此类序列已生成具有高阶位的正值 反转,使其均匀分布在正 64 位 数字空格。
  • 交换键的顺序 使包含单调递增或递减的列 值不是第一个键部分。
  • 对唯一键进行哈希处理并将写入分布到逻辑分片中 方法是创建包含唯一键哈希值的列,以及 然后使用哈希列(或哈希列和唯一键列) 作为主键。这种方法有助于避免热点,因为新行在键空间内的分布更均匀。

为表指定主键后,便无法再更改主键 而无需删除并重新创建表。如需详细了解如何指定主键,请参阅架构和数据模型 - 主键

以下是一个为音乐数据库创建表的 DDL 语句示例 曲目:

GoogleSQL

CREATE TABLE Singers (
  SingerId   INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  SingerInfo BYTES(MAX),
  BirthDate  DATE,
) PRIMARY KEY(SingerId);

PostgreSQL

CREATE TABLE Singers (
  SingerId   bigint NOT NULL,
  FirstName  varchar(1024),
  LastName   varchar(1024),
  SingerInfo bytea,
  BirthDate  date,
  PRIMARY KEY(SingerId)
);

迁移自动生成的密钥

本部分介绍了适用于以下场景的策略和示例 其中,源表已使用自动生成的关键特征:

  • 从使用 UUID 主键的源表迁移。
  • 从使用自动生成的序列整数的源表迁移 键。相关的例子包括但不限于: 数据库支持)、IDENTITY 列(各种数据库支持)、 PostgreSQL SERIAL 数据类型,以及 MySQL AUTO_INCREMENT 列 属性。
  • 从使用位反转键的源表迁移。可能是来源 数据库就是 Spanner,您可以按照指南创建键值对, 对序列值进行位反转

请务必注意,在所有策略中,Spanner 都不 更改从源数据库迁移的数据。您只更改了方法 生成新数据。

迁移 UUID 键列

如果源表使用的是 UUID 列,则可以将该列转换为 STRING 类型,请将值按照 RFC 4122 规范,并使用 GENERATE_UUID() 函数(GoogleSQLPostgreSQL)作为列默认值。例如:

GoogleSQL


CREATE TABLE UserAccessLog (
UserId     STRING(36) DEFAULT (GENERATE_UUID()),
...
) PRIMARY KEY (UserId);

PostgreSQL


CREATE TABLE UserAccessLog (
UserId     varchar(36) DEFAULT SPANNER.GENERATE_UUID(),
...
PRIMARY KEY (UserId)
);

迁移顺序键列

如果源数据库系统为键列生成顺序值, 则可以使用位反序的正序列 (GoogleSQL, PostgreSQL) 来生成在 Spanner 架构中均匀分布的值 64 位正整数空间。为了防止 Spanner 序列,以生成与迁移值重叠的值, 定义一个跳过的范围。例如,您可以跳过 范围为 1 到 4,294,967,296 (2^32) 序列,如果您知道源数据库仅生成 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;

迁移位反转键列

如果您已对键值执行位反操作,以避免 源数据库,也可以使用 Spanner 反转正数, 序列(GoogleSQLPostgreSQL) 继续生成这些值。为避免生成重复值, 可将序列配置为从自定义数字开始计数器。

例如,如果您将数字从 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;