Mysql樹型結構2種方式及相互轉換,mysql樹型結構

來源:互聯網
上載者:User

Mysql樹型結構2種方式及相互轉換,mysql樹型結構

Mysql實現樹型結構,資料庫上常見有2種方式:領接表、預排序遍曆樹(MPTT)。
領接表方式——
主要依賴於一個 parent 欄位,用於指向上級節點,將相鄰的上下級節點串連起來,id 為自動遞增自動,parent_id 為上級節點的 id。
領接表方式的優點在於容易理解,代碼也比較簡單明了。缺點則是遞迴中的 SQL 查詢會導致負載變大,特別是需要處理比較大型的樹狀結構的時候,查詢語句會隨著層級的增加而增加,WEB 應用的瓶頸基本都在資料庫方面,所以這是一個比較致命的缺點,直接導致樹結構的擴充困難重重。
排序遍曆樹方式
現在我們來聊聊第二種方式─預排序遍曆樹方式(即通常所說的 MPTT,Modified Preorder Tree Traversal)。此演算法是在第一種方式的基礎之上,給每個節點增加一個左、右數字,用於標識節點的遍曆順序,如所示:

從根節點開始左邊為 1,然後下一個節點的左邊為 2,以此類推,到最低層節點之後,最低層節點的右邊為其左邊的數字加 1。順著這些節點,我們可以很容易地遍曆完整個樹。根據,我們對資料表做一些改變,增加兩個欄位,lft 和 rgt 用於儲存左右數字( left 和 right 是 MySQL 的保留字,所以改用簡寫)。

可以看出,由於MPTT方式儲存不僅包含隸屬關係,還包括了順序,因此在讀取子樹時不需遞迴,效率大大提高。

下面面討論下如何在這兩著間轉換.

MPTT轉領接表比較容易,只要尋找層級比當前節點小1,且lft<當前節點lft,rgt>當前節點rgt的節點,即為父節點。

領接錶轉MPTT,一般直觀想到的是遞迴產生。但是這個不是尾遞迴,遞迴層數有限制, mysql沒有數組自建堆棧要用表,效率很低,怎麼辦?

筆者設計了一個近似遞推的演算法,分享一下:

首先確定問題:領接表結構(id,pid),目標MPTT表結構(id,lvl,lft,rgt)。

為處理需要,MPTT表增加cnt、seq欄位,用於記錄節點及其子節點的個數、在MPTT中遍曆的序號。

處理過程演算法如下:

1】根節點,轉入MPTT表,令lvl=1,lft=1,rgt=null,cnt=null,seq=1;

2】逐層處理p的子節點,lvl+1;

3】從最底層(lvl最大)向上(lvl遞減)處理各層的節點,cnt=子節點的cnt數+1

4】從最上曾(lvl=1)向下(lvl遞增)處理各層的節點,seq=父節點seq+ sum(id小於本節點的兄弟節點的cnt)+1

5】對每一個節點,lft=seq*2-lvl,rgt = lft +cnt *2 -1

處理結束;

此演算法已在項目中應用,代碼是有著作權的,就不貼了。





著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.