Mysql

是否有一個布爾列來儲存多值屬性的值是否是一個糟糕的微優化?

  • August 5, 2022

這個問題更具理論性。假設有一個實體處於一對多關係中。例如,一篇博文可以有零個或多個標籤。這些標籤儲存在另一個表中(僅包含 2 列 - thepost_id和 the tag)。在 Web 應用程序中,邏輯可能是在獲取文章時獲取並顯示每個文章的所有標籤。有條件地使用has_tags布爾列來知道是否查詢文章標籤(保存查詢)是一種糟糕的微優化實踐嗎?

編輯:我刪除了關於多值屬性標籤的聲明,因為它不正確、具有誤導性並引起混淆。我對此感到抱歉。我不打算在一個列中儲存多個值,而是在一個單獨的表中儲存該問題的答案列出的相同問題。

編輯 2:我想JOIN在問這個問題之前使用 a ,但擔心一旦表開始增長,它可能會導致查詢性能低於第二個查詢(可能是因為在過濾之前在 2 個表之間創建了笛卡爾積,但是我不確定它是否以這種方式實施)。這就是我發布這個問題的原因。

聞起來有點像過早的優化,並且可能沒有太多額外的好處,因為每個Post有 a 的Tag都已經在PostTags表中。因此,對Posts.has_tags列進行過濾不會比表和表JOIN之間的搜尋空間減少更多。Posts``PostsTags

此外,維護額外的索引Posts.has_tags將需要數據庫的更多寫入工作。所以從某種意義上說,它甚至可能是整體性能的淨損失。


順便說一句,在重新閱讀您的文章後,我注意到您特別提到了“*代表文章多值屬性tags*的表格”。正如 Rick James 所說,不要在一個欄位中儲存多個值。相反,PostTags表應該Tag每行有 1 行,Post從而使其與表成為一對多的關係Posts

這將使您能夠更輕鬆地管理和查詢數據。如果您想要查詢Posts共享相同 specific 的 specific ,它也可能會提高性能Tag,並使Tag列上的索引更好。

即使在您想Tag從數據庫中刪除 a 的情況下,它的性能也會更高,因為您可以Tag = 'SomeTag'直接搜尋以獲取所有具有它的行,Tag而不必解析表中每一行的多值Tags列。

儲存posts.has_tags列有風險:它可能不正確。如果有人可能會添加一個標籤而不將其設置has_tags為 true,或者刪除最後一個標籤而不設置has_tags為 false,那麼它不是一個可靠的布爾標誌。post_tags無論如何,您必須檢查表。

您能否執行定期驗證作業以確保布爾標誌正確?你應該多久執行一次?即您的應用程序可以容忍數據錯誤多長時間?

如果您發現差異,例如標誌為真但post_tags表中沒有標籤,那麼哪個是正確的?你應該將標誌設置為真嗎?還是打算將其設置為 false 並刪除標籤,而有人只是忘記了,或者他們嘗試刪除標籤失敗了?你怎麼知道如何糾正數據?

我建議您了解外部連接:

SELECT id, title, content, GROUP_CONCAT(tag) AS tags
FROM posts 
LEFT OUTER JOIN post_tags on posts.id = post_tags.post_id
WHERE posts.id = 1

這是查詢可選數據的方法。如果標籤存在,它們將包含在查詢結果中。如果不存在標籤,標籤列表將為 NULL,但posts仍會返回來自的數據。這就是外連接的工作原理。

如果 post_tags.post_id 被索引,這在效率方面可能已經足夠好了。

然後你就不需要has_tags布爾列了,所有的困難都消失了。

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