本文档包含可帮助您预拆分数据库的信息。
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);
UserId
是 INT64
空间中随机生成的哈希,您需要添加 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
字符串的前缀确定分块,将 UserId
的 UserLocationInfo
表放在 3 个不同的国家/地区,分摊到 3 个不同的分块中:
- 拆分点 1:(1000, "CN")
- 拆分点 2:(1000, "FR")
- 拆分点 3:(1000, "US")
您可以仅使用前缀添加新的拆分点,而无需匹配列或索引的指定格式。在此示例中,拆分点与 LocationId
的指定格式不匹配,仅使用 $COUNTRY
作为前缀。
如果要拆分 UsersByLocation
索引,您可以在 LocationId
列中均分拆分点,或隔离一些预计会接收更多流量的 LocationId
列值:
- 拆分点 1:“CN”
- 拆分点 2:“美国”
- 拆分点 3:“US_NYC”
对于接收更多流量的位置,您可以使用已编入索引的表键部分进一步拆分索引。例如,如果您预计 CN
位置会收到更多流量,则可以引入以下拆分点:
- 拆分点 1:“CN”和 TableKey: (1000, "CN")
- 拆分点 2:“CN”和 TableKey: (2000, "CN")
- 拆分点 3:“CN”和 TableKey: (3000, "CN")
拆分点失效日期
您可以为每个拆分点设置到期时间。根据您的使用场景,将拆分点设置为在预期的流量减少后过期。
默认到期时间为创建或更新分块后的 10 天。允许的最长到期时间为自创建或更新拆分起的 30 天。
分块到期后,Spanner 会接管该分块,并且您无法再查看该分块。Spanner 可能会根据流量合并分块。
您还可以在拆分点过期之前更新其过期时间。例如,如果您增加的流量没有减少,则可以增加拆分到期时间。如果您不再需要拆分点,可以将其设置为立即过期。如需了解如何设置拆分点的到期时间,请参阅如何使拆分点过期。
预拆分数据库的结果
添加拆分点后可能会出现以下结果:
延迟时间变化:添加拆分点是模拟数据库流量增加的一种方式。当数据库的分片越多,读写延迟时间可能就越长,因为事务参与者和查询分片越多。此外,每次读取或写入请求的计算和查询用量也会增加。
拆分点功效:如需确定添加的拆分点是否有益,请监控延迟时间配置文件是否出现最小变化,并监控热点的键可视化工具。如果您发现热点,可以立即使分割点过期,并创建新的分割点。如需详细了解如何使拆分点过期,请参阅如何使拆分点过期。考虑在添加分块的下一次迭代中引入更少的分块,并观察延迟时间概况。
流量增加后的拆分点行为:在流量增加稳定后,应移除添加的拆分点。拆分分布可能不会收敛到负载增加之前的情况。由于流量变化以及支持流量所需的拆分,数据库可能会确定不同的延迟时间配置文件。
用例示例
假设您是一家游戏公司的数据库管理员,并且预计新游戏发布的流量会有所增加。您预期新表为空表的流量。
您需要确保在流量传入时不会出现服务中断,以免对延迟时间或错误率产生可观察的影响。
对于此用例,请考虑以下概要预拆分策略:
确定实例需要多少个节点来支持增加的流量。如需了解如何确定节点数,请参阅性能概览。如果您使用了自动扩缩器,请将上限参数设置为您确定的节点数。此外,将最小限制参数设置为(您确定的节点数 / 5)。
确定哪些表和索引具有最多流量,并且可以从使用拆分点中获得最大收益。分析当前数据,并选择使用自定义拆分点或均匀分布拆分点。
创建拆分点,时间不早于预期流量增加的 7 天至 12 小时。
验证是否已创建分块。如需查看实例上创建的拆分点,请参阅查看拆分点。
注意事项
创建拆分点时,请注意以下事项:
删除表、索引和数据库:在删除表、索引或数据库之前,您需要确保添加的所有相应拆分点都已过期。为此,您可以将拆分到期日设置为当前时间。这是回收实例级配额所必需的。如需详细了解如何使拆分点过期,请参阅如何使拆分点过期。
备份和恢复数据库:系统不会备份添加的分块。您需要在已恢复的数据库上创建分块。
非对称自动扩缩:如果您使用的是非对称自动扩缩,则用于确定拆分点数量的节点数将是所有区域中的最小节点数。
存储空间用量指标暂时增加:添加拆分点会暂时增加“数据库总存储空间”指标,直到 Spanner 完成压缩为止。如需了解详情,请参阅存储空间利用率。仅当现有键范围进一步拆分时才会发生这种情况,新的键范围拆分时不会出现这种情况。
您应该在预期流量增加之前不早于 7 天至 12 小时内创建拆分点。
拆分前的限制
预拆分数据库存在以下限制: