3

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

我的问题来自尝试设计每个编辑器都不同的架构部分。假设将有一个 Docs 表,其中包含有关文档的一般信息(例如 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;

我使用单独表格的原因是将公共部分与任何特定于编辑器的内容隔离开来。

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

这是 1:1 关系的合理结构吗?是否有关于最佳实践的一种或另一种明确的指导?

4

2 回答 2

2

假设您没有接近列限制的风险,Cloud Spanner 可以有效地处理任一选项。如果您计划执行大量 SQL 查询,则使用两表方法可能会更复杂,因为您需要正式连接它们(尽管连接通常应该是有效的,因为数据是交错的)。尽管 JOIN 有额外的 SQL 复杂性,但这可能是更简洁的方法。YMMV。

于 2017-02-16T00:05:51.913 回答
2

在这里回答 CockroachDB,它也支持交错表

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

要像您在示例中提出的那样有意义地交错表格,您可能希望包含一个User表格,然后Docs在其中交错。这将增加用户的所有文档位于同一服务器上的可能性,从而更快地在用户登录后立即返回所有可用文档。这将是您从交错表中获得最大好处的地方(在性能方面)。

但是,您的问题实际上更多是关于数据建模,这是您可能通过外键关系强制执行的问题。这样做的好处是,CockroachDB 中的交错表也明确要求明确说明这些关系(在 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];

这将在一个地方为您提供所需的一切,并且一旦用户单击其中一个文档,您就可以查询特定表格以了解他们正在编辑的文档类型,这是明智的,因为您实际上是在打开不同的程序取决于他们的行动。

于 2017-03-28T17:25:14.773 回答