预分块概览

本文档包含的信息可帮助您对数据库进行预分块。

Spanner 会管理数据库分块,并进行扩缩以应对负载和大小变化。分块与合并是动态的,基于流量来进行。随着分块接收的流量增加,Spanner 会将其细分为更小的范围,并在实例中的其他可用资源间重新分布生成的分块。当分块始终接收较少的流量时,Spanner 会合并分块。

分块不是即时操作。如果分块操作和重新平衡无法跟上流量,分块可能会耗尽其可用的计算和内存资源。发生这种情况时,Spanner 的工作调度器会将后续请求排队,从而增加延迟时间,并可能导致超时和事务中止。

通过对数据库进行预分块,Spanner 可以为可预测的流量增长做好准备。您可以通过创建分块点来对数据库进行预分块。

在以下情况下,请考虑对数据库进行预分块:

  • 您首次将大型数据集加载到 Spanner 数据库内的新表和索引中,例如一次性批量加载。
  • 您预计现有 Spanner 数据库在不久的将来会出现流量负载增加。例如,您可能需要为大流量事件提供支持,例如产品发布或销售活动。

确定分块数量

我们建议为每个节点创建 10 个分块点。由于 Spanner 可以对较小实例快速进行分块和调整以适应流量,因此您无需对较小实例进行预分块。

确定分块点

在确定数据库的分块点时,请考虑以下事项:

  • 如果流量在整个键范围内均匀分布(例如在使用 UUID 或位反转序列键时),请选择可均匀划分流量后键空间的分块点。

  • 如果您的流量集中在一组已知的键范围内,请对这些键范围进行分块并隔离。

  • 如果您预计索引上会产生流量,请对相应索引使用分块点。

  • 如果向父表中添加了分块点,交织表也会进行分块。如果您预计交织表上的流量会更高,请务必在对应的交织表中使用分块点。

  • 您可以根据架构对象的流量增长比例来向其分配分块点。

确定分块点的示例工作流

假设您的数据库具有由以下 DDL 定义的表结构:

CREATE TABLE UserInfo (
 UserId INT64 NOT NULL,
 Info BYTES(MAX),
) PRIMARY KEY (UserId);


CREATE TABLE UserLocationInfo (
 UserId INT64 NOT NULL,
 LocationId STRING(MAX) NOT NULL,
 ActivityData BYTES(MAX),
) PRIMARY KEY (UserId, LocationId), INTERLEAVE IN PARENT UserInfo ON DELETE CASCADE;


CREATE INDEX UsersByLocation ON UserLocationInfo(LocationId);

UserIdINT64 空间中随机生成的哈希,您需要添加 100 个分块点,以均匀分布 UserInfo 表及其交织表上的预期流量增长。由于分块点均匀分布,因此您需要找到每个分块点之间的行数,即 offset

offset = UserId 范围的最大值/99

然后,根据 UserId 的第一行(或 UserId_first)确定表 UserInfo 的分块点。如需确定第 N 个分块点,请使用以下计算公式:

分块点 N:UserId_first + (offset * (N-1))

例如,第一个分块点是 UserId_first + (offset * 0),第三个分块点是 UserId_first + (offset * 2)。

由于 UserLocationInfo 表是 UserInfo 表的交织表,因此也会在 UserId 边界处进行分块。您可能还想在 UserLocationInfo 表中的 LocationId 列上创建分块点。

请注意,LocationId 采用 $COUNTRY_$STATE_$CITY_$BLOCK_$NUMBER 格式,例如 US_CA_SVL_MTL_1100_7

对于 UserId,您可以根据 LocationId 字符串的前缀确定分块,以便针对 UserIdUserLocationInfo 表放置在 3 个不同分块中的 3 个不同国家/地区:

  • 分块点 1:(1000, "CN")
  • 分块点 2:(1000, "FR")
  • 分块点 3:(1000, "US")

您只需使用前缀即可添加新的分块点,无需与列或索引的指定格式匹配。在此示例中,分块点与 LocationId 的指定格式不匹配,并且仅使用 $COUNTRY 作为前缀。

如果您想对 UsersByLocation 索引进行分块,可以将分块点均匀分布在 LocationId 列上,也可以隔离预计会收到更多流量的几个 LocationId 列值:

  • 分块点 1:"CN"
  • 分块点 2:"US"
  • 分块点 3:"US_NYC"

对于会收到更多流量的位置,您可以使用索引表键部分进一步对索引进行分块。例如,如果您预计 CN 位置会收到更多流量,则可以引入以下分块点:

  • 分块点 1:"CN" 和 TableKey:(1000, "CN")
  • 分块点 2:"CN" 和 TableKey:(2000, "CN")
  • 分块点 3:"CN" 和 TableKey:(3000, "CN")

分块点失效

您可以为每个分块点设置失效时间。根据您的应用场景,将分块点设置为在预期流量增加消退后失效。

默认失效时间是自分块创建或更新起计算的 10 天。允许的最长失效时间是自您创建或更新分块起计算的 30 天。

分块失效后,Spanner 会接管分块管理,您将无法再查看分块。Spanner 可能会根据流量合并分块。

您还可以在分块点失效之前更新其失效时间。例如,如果流量增加没有消退,您可以延长分块失效时间。如果您不再需要某个分块点,可以将其设置为立即失效。如需了解如何设置分块点的失效时间,请参阅如何使分块点失效

对数据库进行预分块的结果

添加分块点后,可能会出现以下结果:

  • 延迟时间变化:添加分块点是一种模拟数据库流量增加的方法。当数据库的分块数量增加时,由于事务参与者和查询分块数量增加,读取和写入延迟时间可能会持久增加。您还可以预计到每个读取或写入请求的计算和查询用量会增加。

  • 分块点效果:如需确定添加的分块点是否有益,请监控延迟时间模式以了解是否存在微小变化,并监控 Key Visualizer 以了解是否存在热点。如果您发现热点,可以立即使分块点失效并创建新的分块点。如需详细了解如何使分块点失效,请参阅如何使分块点失效。可考虑在下一次添加分块的迭代中引入较少数量的分块,并观察延迟时间模式。

  • 流量增加后的分块点行为:在流量增加稳定后,应移除添加的分块点。分块分布可能不会收敛到负载增加之前的状况。由于流量变化以及支持流量所需的分块,数据库可能会形成不同的延迟时间模式。

用例示例

假设您是一家游戏公司的数据库管理员,并且预计新游戏发布时流量会增加。您预计空的新表上会有流量。

您需要确保流量增加时服务不会中断,以免对延迟时间或错误率产生明显影响。

对于此应用场景,请考虑以下高级预分块策略:

  1. 确定实例为增加的流量提供支持所需的节点数量。如需了解如何确定节点数量,请参阅性能概览。如果您在使用自动扩缩器,请将上限参数设置为您确定的节点数量。此外,请将下限参数设置为您确定的节点数量除以 5 的值。

  2. 确定流量最大的表和索引,这些表和索引从分块点受益最多。分析当前数据,然后选择使用自定义分块点还是均匀分布的分块点。

  3. 创建分块点的时间不早于预期流量增加前 7 天,也不晚于预期流量增加前 12 小时。

  4. 验证是否已创建分块。如需查看实例上创建的分块点,请参阅查看分块点

注意事项

创建分块点时,请考虑以下注意事项:

  • 表、索引和数据库删除:在删除表、索引或数据库之前,您需要确保所有添加的相应分块点都已失效。为此,您可以将分块失效日期设置为当前时间。这是回收实例级配额所必需的。如需详细了解如何使分块点失效,请参阅如何使分块点失效

  • 备份和恢复数据库:不会备份添加的分块。您需要在恢复的数据库上创建分块。

  • 非对称自动扩缩:如果您使用非对称自动扩缩,则用于确定分块点数量的节点数量是所有区域中的最小节点数量。

  • 存储空间用量指标暂时增加:添加分块点会暂时增加数据库总存储空间指标,直到 Spanner 完成压缩为止。如需了解详情,请参阅存储空间利用率。这种情况只有在进一步对现有键范围进行分块时才会出现,而在对新键范围进行分块时不会出现。

  • 创建分块点的时间不应早于预期流量增加前 7 天,也不应晚于预期流量增加前 12 小时。

预分块限制

对数据库进行预分块存在以下限制:

  • 您无法对搜索索引进行预分块。您只需对基表进行预分块。如需了解详情,请参阅搜索索引分片

  • 您无法预先拆分向量索引。如需详细了解向量索引,请参阅向量索引

  • 如需了解分块点的配额,请参阅配额和限制

后续步骤