怎樣在 MySQL 表中存儲樹形結構數據?

需求:

  1. 文檔型數據,結構是樹形的,如圖:
  2. 想要讀取生成樹形結構、添加子節點、查找修改數據的代價最小。


一般比較普遍的就是四種方法:(具體見 SQL Anti-patterns這本書)

Adjacency List:每一條記錄存parent_id

Path Enumerations:每一條記錄存整個tree path經過的node枚舉

Nested Sets:每一條記錄存 nleft 和 nright

Closure 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)的源碼進行修改後必須也開源嗎?

TAG:資料庫 | MySQL | 數據結構 |