将 INTERLEAVE 表用于一对一关系

Using INTERLEAVE tables for 1-to-1 relationships

我正在为一组文档编辑器(电子表格编辑器、文本文档编辑器、powerpoint 编辑器等)设计架构。编辑们将共享一个数据库,尽管他们有一天可能会使用单独的数据库。每个编辑器共享每个文档的许多公共信息,但是根据文档的类型,还有特定于编辑器的信息。

我的问题来自于尝试设计每个编辑器都不同的架构部分。假设将有一个 Docs table,它包含有关文档的一般信息(例如,ID)。最重要的是,我想关联特定编辑器的特定信息,该编辑器与 Doc 记录有 1:1 关系。我建议的模式是:

CREATE TABLE Docs (
  DocId STRING(MAX) NOT NULL,
  CreationTime TIMESTAMP NOT NULL,
  ....
) PRIMARY KEY (DocId);

CREATE TABLE SpreadsheetStuff (
  DocId STRING(MAX) NOT NULL,
  ... spreadsheet-specific information here ...
) PRIMARY KEY (DocId),
  INTERLEAVE IN PARENT Docs
  ON DELETE CASCADE;

CREATE TABLE TextDocumentStuff (
  DocId STRING(MAX) NOT NULL,
  ... text-document-specific information here ...
) PRIMARY KEY (DocId),
  INTERLEAVE IN PARENT Docs
  ON DELETE CASCADE;

我之所以使用单独的 table 是为了将公共部分与任何特定于编辑器的内容隔离开来。

我想知道这是否是不必要的,因为编辑者可以根据需要根据自己的需要更改文档 table,即使这种结构在技术上是可行的。换句话说,我可以在文档 table 中添加大量额外的列,其中包含特定于编辑器的信息。一个问题是我提出的结构可能具有不明显的性能或其他影响。

对于 1:1 关系来说,这是一个合理的结构吗?是否有关于最佳实践的明确指导?

Cloud Spanner 可以有效地处理任一选项,前提是您不会冒险接近专栏 limit。如果您计划执行大量 SQL 查询,使用 two-table 方法可能会更复杂,因为您正式需要加入它们(尽管加入通常应该是有效的,因为数据是交错)。尽管 JOIN 额外 SQL 复杂,但这可能是更简洁的方法。 YMMV.

在这里回答 CockroachDB,它也支持 interleaving tables

交错 tables 背后的想法很简单,因此数据的布局方式使经常一起读取的数据位于同一台服务器上,这需要更少的行程。它是一种提高性能的工具,而不是对数据建模明确有用的工具。

要像您在示例中提议的那样有意义地交错 table,您可能希望包括 User table,然后交错 Docs 在那里。这将增加用户的所有文档都位于同一服务器上的可能性,从而可以更快地 return 用户登录后立即访问所有可用文档。这将是您获得最大收益的地方交错 tables(在性能方面)。

但是,您的问题实际上更多地是关于数据建模的,这是您可以通过外键关系强制实施的问题。这样做的好处是,它也是 CockroachDB 中交错 table 明确要求明确说明这些关系(这在 Cloud Spanner 中似乎不需要)。

使用您的示例模式,这就是 CockroachDB 中的样子:

CREATE TABLE Users (
  UserId INT PRIMARY KEY,
  ...,
);

CREATE TABLE Docs (
  UserId INT,
  DocId INT,
  CreationTime TIMESTAMP NOT NULL,
  ...,
  PRIMARY KEY (UserId, DocId),
  CONSTRAINT fk_Users FOREIGN KEY (UserId) REFERENCES Users
)  INTERLEAVE IN PARENT Users (UserId);

CREATE TABLE SpreadsheetStuff (
  UserId INT,
  DocId INT,
  PRIMARY KEY (UserId, DocId),
  ... spreadsheet-specific information here ...
  CONSTRAINT fk_Docs FOREIGN KEY (UserId, DocId) REFERENCES Docs
) INTERLEAVE IN PARENT Docs (UserId, DocId);

CREATE TABLE TextDocumentStuff (
  UserId INT,
  DocId INT,
  PRIMARY KEY (UserId, DocId),
  ...text-document-specific information here ...
  CONSTRAINT fk_Docs FOREIGN KEY (UserId, DocId) REFERENCES Docs
) INTERLEAVE IN PARENT Docs (UserId, DocId);

当用户登录时,您想要编写的查询可能类似于:

SELECT * FROM Docs WHERE UserId = [this User's ID];

这会在一个地方为您提供所需的一切,一旦用户单击其中一个文档,您就可以查询特定的 table 他们正在编辑的文档类型,即这是明智的,因为您实际上是在根据他们的操作打开不同的程序。