怎樣在 MySQL 表中存儲樹形結構數據?
需求:
- 文檔型數據,結構是樹形的,如圖:
- 想要讀取生成樹形結構、添加子節點、查找修改數據的代價最小。
一般比較普遍的就是四種方法:(具體見 SQL Anti-patterns這本書)
Adjacency List:每一條記錄存parent_idPath Enumerations:每一條記錄存整個tree path經過的node枚舉
Nested Sets:每一條記錄存 nleft 和 nrightClosure Table:維護一個表,所有的tree path作為記錄進行保存。各種方法的常用操作代價見下圖
推薦一本書 SQL Anti-patterns,見:http://www.ppurl.com/2010/06/sql-antipatterns-avoiding-the-pitfalls-of-database-programming.html其中對於樹形結構在關係型資料庫中的存儲做了分析。一共有4種方式。各有優劣,主要是跟據業務需求來決定的。樓主可以借鑒下就是節點與節點之間的關係,與商品的分類也類似,你設計成父子欄位,並且標記之間的關係圖譜就是,在業務支持通用性、分類調整成本、查找成本等多個維度權衡即可!
參考這個:
http://xiwei-wang.blog.163.com/blog/static/32674110201172282055553/介紹我發現的2種樹形結構存儲方法,原理圖如下:第一種方法:用多個資料庫列存儲佔位符(有限深度樹)第二種方法:用數字來表示深度,並用groupid來分組(無限深度樹)
詳見 http://drinkjava2.iteye.com/blog/2353983,優點是簡單易懂,SQL查/插/刪/操作方便,缺點是節點移動操作麻煩。
最近更新: 還是採用sql資料庫實現的,很簡單。
最近處理雲盤系統也面臨這個問題,準備採用No-sql 資料庫結合json 來實現,參考文檔如下:Storing Hierarchical Data in a Database資料庫存儲樹形結構的數據希望對你有幫助。沒有萬全的方案,根據自己的場景是查詢多,更新、刪除少,亦或是更新、刪除多,查詢少,來做方案權衡,上面 @盧鈞軼 同學提到的Adjacency List、Path Enumerations、Nested Sets、Closure Table這幾個解決方案是比較流行靠譜的做法了。
Path Enumerations 靠譜一些。
隨著SQL資料庫的發展,現在的流行資料庫已經為樹形結構的查詢進行了優化,基本支持 CTE標準裡面的With Recursive語句。這個語句對Adjacency List(每一條記錄存parent_id)大部分常見查詢性能很高。你可以看一下這篇文章:Adjacency list vs. nested sets: PostgreSQL 我們也自己對幾種常見操作進行了性能測試(100w Rows):
Operation Adjacency List Nested
Find immediate decendants尋找下面只有一層的子節點 9ms 97ms
Find all descendants of a given node找到下面所有子節點 580ms 120ms
Find all ancestors of a given node 9ms 3606ms
Find all descendants of a given node up to 2 levels 13ms 98ms
Add descendants/Remove descendants ---- 都很快,沒有差別
簡單說,樹無非就是節點+關係;你用db把這些信息保存起來就ok了,剩下的就是性能的差異了。
推薦閱讀:
※用戶和管理員同時操作同一記錄的不同欄位,如果做並發控制?
※MySQL 對於千萬級的大表要怎麼優化?
※如何解決主從資料庫同步延遲問題?
※mysql DBA技術難度低為什麼工資比oracle高?
※將開源軟體(比如mysql)的源碼進行修改後必須也開源嗎?