我为我的 Spanner 数据库设计了一个表模式,它利用交错表来存储关联的记录。我这样做是为了优化阅读时间。我的架构看起来像:
CREATE TABLE all_ids (
userid INT64 NOT NULL,
) PRIMARY KEY(userid);
CREATE TABLE connections_in (
userid INT64 NOT NULL,
child_userid INT64 NOT NULL,
connect_time TIMESTAMP NOT NULL,
) PRIMARY KEY(userid, child_userid),
INTERLEAVE IN PARENT all_ids ON DELETE CASCADE;
CREATE TABLE connections_out (
userid INT64 NOT NULL,
child_userid INT64 NOT NULL,
connect_time TIMESTAMP NOT NULL,
) PRIMARY KEY(userid, child_userid),
INTERLEAVE IN PARENT all_ids ON DELETE CASCADE;
connections_in
和 connections_out
表存储用户数据库中节点之间的图形连接。每个用户最多可能有几百个连接。
我还想随着时间的推移存储每个用户的元数据历史记录,我不确定将该数据交错到父表中是否有意义
all_ids
。随着时间的推移,每个用户都有数千行元数据:
CREATE TABLE user_metadata (
userid INT64 NOT NULL,
snapshot_time TIMESTAMP NOT NULL,
username STRING(1024) NOT NULL,
user_description STRING(1024) NOT NULL,
) PRIMARY KEY(userid, snapshot_time DESC),
INTERLEAVE IN PARENT all_ids ON DELETE CASCADE;
我知道 spanner 使用字典顺序对主键进行排序,这是否意味着
user_metadata
表中的一行可以在物理上与 connections_in
或 connections_out
中的行并置,因为两个主键的第一部分是从桌子上取的all_ids
?如果是这样,这是否意味着基于 userid 从 connections_in/_out
读取时间会比如果我在同一个数据库中为 user_metadata
创建一个单独的非交错表要慢?:
CREATE TABLE user_metadata (
userid INT64 NOT NULL,
snapshot_time TIMESTAMP NOT NULL,
username STRING(1024) NOT NULL,
user_description STRING(1024) NOT NULL,
) PRIMARY KEY(userid, snapshot_time DESC);
非常感谢任何帮助!
Spanner 使用交错在同一个 split 中配置数据,因此将相关数据分配到同一个计算节点以进行处理和连接。这并不是真正的逐行机制;插入
user_metadata
记录不一定会导致 all_ids
记录将磁盘扇区移动到远离 connections_out
记录或类似内容的位置。
在拆分级别,可能会对性能产生影响,但答案是“视情况而定”。有两种情况:
userid
是高基数假设您有 100 个 Spanner 节点和 1,000,000 个不同的用户 ID(每个用户的使用率至少大致相同)。在这种情况下,Spanner 通常不需要查看键列表中的第二个键,以便在集群周围合理均匀地均匀分布数据,并且倾向于尝试仅通过第一个键来保持集群(
userid
) 性能和简单性。所以每个用户的所有数据都将存储在一起,即使你有一堆交错的表。
userid
是低基数假设您有 100 个 Spanner 节点和 8 个用户。但是这些用户每个人都有很多很多 connection_in、connection_out 和/或 user_metadata 记录。在这种情况下,Spanner 将希望跨多个 Spanner 节点拆分每个用户的数据,以便它可以充分利用 100 节点集群。在这种情况下,将单个用户的所有数据重新连接在一起将需要来自多个 Spanner 节点的数据——这是一个分布式 JOIN,(一般来说)比将所有数据都放在单个节点本地更昂贵。
如果您有大量用户,但其中一个用户在其不同子记录上的请求/秒比其他用户多得多,Spanner 可能会决定拆分与那个超大
userid
关联的记录。这不是一个常见的情况,但如果您有严重的数据和负载偏差作为一种方法来避免使处理该用户的工作负载的单个 Spanner 节点过载并导致更大的延迟峰值,则可能会发生这种情况。