Sql-Server

有沒有更好的方法來處理多級 ParentId 表結構?

  • May 25, 2021

我在一家出版商工作,我們的產品主要是書籍和期刊。它們最常見的結構如下:

Book > Chapter

Book Series > Book > Chapter

Book > Volume > Chapter

Book Series > Book > Volume > Chapter

Journal > Volume > Issue > Article

Journal > Volume > Article

我們目前將所有這些記錄儲存在具有 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

所有這些記錄,無論是書籍、章節、期刊、文章等,都可以將其 ID 連接到其他表,以獲取作者、價格、所有權等資訊。

這種結構給我們帶來的問題是嵌套在某些情況下會增加大量成本。例如,如果有人試圖訪問他們購買的期刊文章,我們需要執行多個查詢以了解他們是否確實有權訪問。我們有一個包含所擁有產品的 Id 的所有權表,因此我們不僅需要檢查使用者是否直接擁有期刊文章的 Id,還需要檢查文章的父期、捲和期刊的 Id 的所有權。(即,如果使用者擁有整個期刊,則暗示他們擁有該期刊中的所有文章,儘管沒有明確的訪問權限。)所以我們的主要“所有權”查詢相當龐大,因為我們需要它來檢查所有權嵌套級別。

類似的情況還有很多。例如,如果我們需要獲取與一本書關聯的所有作者,我們需要直接執行該書的查詢,然後走到每一章並獲取每一章的所有作者,或者如果這本書有捲,我們需要遍歷每卷,並獲得每卷章節的作者。

另一種情況是搜尋,我們需要基本上聚合所有這些不同的類型以被視為相對平等,以便可以對它們執行搜尋,以及結果,無論它們是一本書、章節、期刊、文章等,都需要在搜尋結果中並排出現。

我想知道是否有一種方法可以改進我們的設置,以便我們可以更快地獲取關係數據(例如所有權檢查、作者、價格等),方法是:

  1. 重構我們的主表以擺脫 Id/ParentId 設置,或者,
  2. 在旁邊建構新的表/視圖。

我對任何人對我們目前設置或提出新設置的任何評論/建議/建議感興趣。

我將始終儲存中間實體,可能通過將缺少的實體添加為虛擬條目,以便您始終可以使用相同的查詢進行查詢。

例如,商店

書籍>章節

作為

叢書(木偶)>書籍> 卷(木偶)>章節

現在,您可以查詢

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

whereBookSeriesVolume將產生 NULL 列,除了主鍵和外鍵。

因此,始終以所需級別開始BookSeries和結束儲存。所以如果你想儲存一本沒有捲也沒有章節的書,這很好。該查詢將為捲和章節(包括主鍵和外鍵)生成 NULL 列。LEFT JOIN 確保了這一點。

期刊有不同的結構。這裡有兩種可能的方法:

  1. 將日記帳作為獨立層次結構儲存在其他表中。
  2. (部分)統一兩個層次結構並使用TypeorKind欄位作為鑑別器來區分書籍和期刊
BookSeries > BookOrJournal > Volume +--> Issue > Article
                                   |
                                   \--> Chapter

我認為 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/

引用自:https://dba.stackexchange.com/questions/292161