有没有更好的方法来处理多级 ParentId 表结构?

Str*_*ped 6 performance database-design sql-server query-performance

我在一家出版商工作,我们的产品主要是书籍和期刊。它们最常见的结构如下:

Book > Chapter

Book Series > Book > Chapter

Book > Volume > Chapter

Book Series > Book > Volume > Chapter

Journal > Volume > Issue > Article

Journal > Volume > Article
Run Code Online (Sandbox Code Playgroud)

我们目前将所有这些记录与 Id 和 ParentId 列存储在同一个表中。例如,TitleId = 1 的书有 3 章将具有以下行:

Book: Id = 1, ParentId = 1
Chapter #1: Id = 2, ParentId = 1
Chapter #2: Id = 3, ParentId = 1
Chapter #3: Id = 4, ParentId = 1
Run Code Online (Sandbox Code Playgroud)

所有这些记录,无论是书籍、章节、期刊、文章等,都可以将它们的 Id 连接到其他表,以获取作者、价格、所有权等信息。

这种结构给我们带来的问题是嵌套在某些情况下会增加大量开销。例如,如果有人试图访问他们购买的期刊文章,我们需要运行多个查询来了解他们是否确实有权访问。我们有一个包含自有产品 Id 的所有权表,因此我们不仅需要检查用户是否直接拥有期刊文章的 Id,还需要检查文章的父期、卷和期刊的 Id 的所有权。(即,如果用户拥有整个期刊,则暗示他们拥有该期刊中的所有文章,尽管没有明确的访问权限。)所以我们的主要“所有权”查询相当庞大,因为我们需要它尽可能检查所有权嵌套级别。

类似的情况还有很多。例如,如果我们需要获取与一本书相关联的所有作者,我们需要直接运行该书的查询,然后深入到每一章并获取每一章的所有作者,或者如果这本书有卷,我们需要走下每一卷,并获得每卷章节的作者。

另一种情况是搜索,我们需要基本上将所有这些不同类型聚合起来,以使其相对相等,以便可以对它们进行搜索,结果,无论它们是书籍、章节、期刊、文章等,所有这些都需要在搜索结果中并排出现。

我想知道是否有办法改进我们的设置,以便我们可以通过以下任一方式更快地获取关系数据(例如所有权检查、作者、价格等):

  1. 重构我们的主表以摆脱 Id/ParentId 设置,或者,
  2. 在旁边建立新的表/视图。

我对任何人对我们当前设置或提出新设置的任何评论/建议/建议感兴趣。

Oli*_*bes 6

我将始终存储中间实体,可能通过将缺失的实体添加为虚拟条目,以便您可以始终使用相同的查询进行查询。

例如,商店

书籍>章节

作为

丛书(哑)>>卷(哑)>

现在,您可以查询

SELECT * 
FROM
   BookSeries bs
   LEFT JOIN Book b      ON bs.BookSeriesID = b.BookSeriesID 
   LEFT JOIN Volume v    ON b.BookID = v.BookID
   LEFT JOIN Chapter c   ON v.VolumeID = c.VolumeID
Run Code Online (Sandbox Code Playgroud)

where BookSeriesandVolume将产生 NULL 列,除了主键和外键。

因此,始终BookSeries以所需级别开始和结束进行存储。所以如果你想存储一本没有卷没有章的书,这很好。该查询将为卷和章(包括主键和外键)生成 NULL 列。这是由 LEFT JOIN 确保的。

期刊有不同的结构。这里有两种可能的方法:

  1. 将日记帐作为独立的层次结构存储在其他表中。
  2. (部分)统一两个层级,并使用 a TypeorKind字段作为鉴别器来区分书籍和期刊
    BookSeries > BookOrJournal > Volume +--> Issue > Article
                                        |
                                        \--> Chapter
    
    Run Code Online (Sandbox Code Playgroud)


Ste*_*o64 5

我认为 Olivier 的建议很好。请注意,SQL Server 有一种特殊的数据类型用于处理称为hierarchyid 的层次结构。根据您提供的信息,我没有看到任何会阻止您使用此数据类型的内容。

您可以在以下位置阅读更多信息:- https://docs.microsoft.com/en-us/sql/t-sql/data-types/hierarchyid-data-type-method-reference?view=sql-server-ver15

网络上也有很多关于如何存储层次结构和各种不同技术的讨论。

您可以从这篇文章开始,其中包含一些经典参考资料

https://www.red-gate.com/simple-talk/sql/performance/the-performance-of-traversing-a-sql-hierarchy/