是否有一個布爾列來儲存多值屬性的值是否是一個糟糕的微優化?
這個問題更具理論性。假設有一個實體處於一對多關係中。例如,一篇博文可以有零個或多個標籤。這些標籤儲存在另一個表中(僅包含 2 列 - the
post_id
和 thetag
)。在 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
布爾列了,所有的困難都消失了。