sqlite3樹形結構遍歷效率對照測試


sqlite3樹形結構遍歷效率對照測試

一、緣起

項目數據結構:本人從事安防行業,視頻監控領域。項目中會遇到監控點位的組織機構划分、暫時划分的巡邏點位等。這些相機點位、連同組織機構,它們在邏輯關系上構成了一個樹形結構。

又因為不論什么一個點位屬於一個組織機構,也可能屬於一個被暫時創建的視頻巡邏計划中,因此,能夠看出,不論什么一個節點,包含相機節點和組織機構節點,都有可能有至少一個父級節點,且不論什么一個組織機構節點也會有多個下級子節點。這中邏輯關系又構成了圖。

數據量規模:一個市級別的管理平台,點位數量在十萬至幾十萬級別。一個省級別的管理平台,所接入的點位規模在百萬級別。

問題:監控平台常常須要用到的功能,就是要高速查詢出來一個節點下的全部子節點、子節點的子節點等的樹形結構。


我們的數據庫眼下採用的是sqlite3。
眼下須要對查詢遍歷部分做性能上的優化,由我來承擔完畢這項工作。本人無數據庫方面開發的經歷。僅僅用了一天時間嘗試了例如以下4種方案。或許還有最好的。親愛的讀者您看到了這篇帖子,假如知道有更好的方法,還請賜教,筆者不勝感激。

因為一些原因。在這里不便於公開各個方案的代碼、sql語句、或sqlite表結構等信息。還請諒解。

二、方案

從上面的數據結構能夠看出,要想查詢到一個節點的全部子節點,通常的做法是必須使用遞歸的方法。這就有了方案1、2、3。假設轉換一下思路。則就產生方案4。

方案1:multimap遞歸查詢
因為每一個節點極其父節點構成一個pair,這恰巧和STL中的multimap的數據模型一致。所以自然考慮到使用multimap實現遞歸遍歷的方案。

詳細例如以下:

(1)從數據庫中查詢全部的數據。
(2)將查詢的結果集插入(insert)到multimap中。

(3)用遞歸的方法遍歷查詢到multimap中的節點及全部樹形子節點。

方案2:函數遞歸查詢
方案1是將全部數據都查詢出來,然后在multimap中遞歸查找。方案2的思路是。查找這個節點的子節點,然后查找子節點的子節點,然后查找子節點的子節點的子節點......(子子孫孫無窮匱也)。實現方法是編寫一個遞歸函數,遞歸地查詢數據庫,即遞歸地select。
(1)從數據庫中查詢全部的父節點是“傳入節點”的節點記錄。
(2)從(1)中的結果集中,取出查詢到的節點id,將這個節點作為“父節點”,然后又一次運行(1)。
(3)由(1)和(2),假設某一次遍歷的結果集為空。則表示當前遍歷到的這個節點是葉子節點,它沒有子節點了。

則遞歸函數退出。


方案3:sql語句遞歸查詢

方案1、2的思路都是在sql語句之外遞歸查詢。

假設可以寫出遞歸的sql語句,效果是不是能更好呢?於是有了方案3。簡單來說。方案3是將方案2中用函數實現的"查找子節點的子節點的子節點......"。替換為用sql語句來實現。

關於sqlite3的遞歸語句,請參考我的另外一篇博文《sqlite3-遞歸查詢》。

這里要注意一下,sqlite3的遞歸語法 with recursive 可能在 其3.7.X 及下面版本號不受支持,可能會提示語法錯誤syntax error。我的sqlite3庫升級到3.8.x之后就能查詢到結果了。


方案4:引入關系表

如今數據庫表的結構例如以下圖所看到的。


它是一種結構化的數據庫表結構

將節點的id和父節點id都存儲在一個記錄中。

優點是開發時候高速。壞處是,不便於擴展和改動。

說它不便於擴展,是由於假如一個節點有兩個父節點。則一個字段無法滿足。再加一個father_id字段嗎?顯然不現實,由於不知道會有多少個父節點。

說它不便於改動,是由於。假設將多個父節點id都採用格式化都填入father_id字段。則在維護記錄的時候會帶來“拼串和解析串”的步驟,帶來維護上的麻煩。

那么。能否夠換一種思路,採用面向對象的思維創建數據庫表呢?於是想到了以下的表結構和表關系。

如圖所看到的。添加一個關系表,專門用來存儲節點之間的關系。

將father_id和son_id作為聯合主鍵。

如此一來,節點與節點之間的關系,事實上就相應的是關系表中的一條記錄!一個節點有多少個子節點,關系表中就有多少條記錄。一個節點有多少個父節點。也是這樣。

這樣改造了數據庫表之后。帶來的優點是顯而易見的。

首先是可維護性的提升。

從曾經的解析改動表字段,到如今的插入刪除一條或多條記錄。

其次是開發維護人員對於數據的關系也會理解地更加深刻和清楚。

但不可避免,也有不足之處。

首先是開發的成本。這種表結構和表關系。不利於高速開發。

其次是如今的軟件系統已經用了好幾年。突然改動,可能會造成現場維護上的壓力突然增大。

第三,這種結構。是否滿足業務功能要求的效能,還是個未知數。


三、結果對照

以下給出上述方案1、2、3的測試對照表。

方案1



方案2



方案3



從理論上來講。查詢得到結果的效率是 方案3 > 方案1 > 方案2。

從上面3個表來看,結果的確如期望的那樣。

可是,有些意外的是。方案3中從結果集中獲取下一條記錄這一步驟(即next),太占用時間,居然達到了97%的占比。

從綜合效率上來看,方案1時間最快。其次是方案3,最慢的是方案2。

由於方案2要運行大量的函數遞歸調用。函數棧切換。這是最為耗時的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM