嵌套集合模型(Nested set model)介紹

原文鏈接:www.pilishen.com/posts/an-in…

此文檔是 nestedset-無限分類正確姿勢的擴展閱讀

本文翻譯自維基百科Nested set model

nested set model(嵌套集合模型)是一種在關系型數據庫中表示nested sets(嵌套集合)?的特殊技術。[nested sets]通常指的是關系樹或者層級關系。這個術語是由?Joe Celko清晰的提出來的,還有人使用不同的術語來描述這一技術。

誘因

該技術的出現解決了標準關系代數和關系演算以及基于它們的SQL操作不能直接在層次結構上表示所有期望操作的問題。層級可以用parent-child relation (父子關系)術語來表示 - Celko稱之為?[adjacency list model],但是如果可以有任意的深度,這種模型不能用來展示類似的操作比如比較兩個元素的層級或者確定一個元素是否位于另一個元素的子層級,當一個層級結構是固定的或者有固定的深度,這種操作必須通過每一層的?relational join?(關系連接)來實現。但是這將很低效。這通常被稱為物料清單問題。

通過切換到圖形數據庫,可以很容易地表達層次結構。另外在一些關系型數據庫系統中存在并提供了這種關系模型的解決方案:

  • 支持專門的層級結構數據類型,比如SQL的hierarchical query?facility(層級查詢工具)。
  • 使用層級操作擴展關系型語言,比如?nested relational algebra。
  • 使用transitive closure擴展關系型語言,比如SQL的CONNECT語句;這可以在parent-child relation 使用但是執行起來比較低效。
  • 層級結構查詢可以在支持循環且包裹關系的操作的語言中實現。比如?PL/SQL,?T-SQL?or a?general-purpose programming language

當這些解決方案沒被提供或不容易實現,就必須使用另一種方法

技術

嵌套集模型是根據樹遍歷來對節點進行編號,遍歷會訪問每個節點兩次,按訪問順序分配數字,并在兩次訪問中都分配。這將為每個節點留下兩個數字,它們作為節點兩個屬性存儲。這使得查詢變得高效:通過比較這些數字來獲得層級結構關系。但是更新數據將需要給節點重新分配數字,因此變得低效。盡管很復雜但是可以通過不使用整數而是用有理數來改進更新速度。

例子

在衣服庫存目錄中,衣服可能會更加層級機構來分類:

處于層級結構頂端的Clothing分類包含所有的子類,因此它的左值和右值分別賦值為1和22,后面的值即這里的22是展現的所有節點總數的兩倍。下一層級包含Men's和Women's兩子類,各自包含必須被計算在內的層級。每一層的節點都根據它們包含的子層級來給左值和右值賦值。如上表所示。

表現

使用nested sets 將比使用一個遍歷adjacency list的儲存過程更快,對于天生缺乏遞歸的查詢結構也是更快的選擇。比如MySQL.但是遞歸SQL查詢語句也能提供類似“迅速查詢后代”的語句并且在其他深度搜索查詢是更快,所以也是對于提供這一功能的數據庫的更快選擇。例如?PostgreSQL,[5] ?Oracle,[6] ?and?Microsoft SQL Server.[7]

缺點

The use case for a dynamic endless database tree hierarchy is rare. The Nested Set model is appropriate where the tree element and one or two attributes are the only data, but is a poor choice when more complex relational data exists for the elements in the tree. Given an arbitrary starting depth for a category of 'Vehicles' and a child of 'Cars' with a child of 'Mercedes', a foreign key table relationship must be established unless the tree table is naively non-normalized. Attributes of a newly created tree item may not share all attributes with a parent, child or even a sibling. If a foreign key table is established for a table of 'Plants' attributes, no integrity is given to the child attribute data of 'Trees' and its child 'Oak'. Therefore, in each case of an item inserted into the tree, a foreign key table of the item's attributes must be created for all but the most trivial of use cases. If the tree isn't expected to change often, a properly normalized hierarchy of attribute tables can be created in the initial design of a system, leading to simpler, more portable SQL statements; specifically ones that don't require an arbitrary number of runtime, programmatically created or deleted tables for changes to the tree. For more complex systems, hierarchy can be developed through relational models rather than an implicit numeric tree structure. Depth of an item is simply another attribute rather than the basis for an entire DB architecture. As stated in?SQL Antipatterns:[8]

Nested Sets is a clever solution – maybe too clever. It also fails to support referential integrity. It’s best used when you need to query a tree more frequently than you need to modify the tree.[9]

The model doesn't allow for multiple parent categories. For example, an 'Oak' could be a child of 'Tree-Type', but also 'Wood-Type'. An additional tagging or taxonomy has to be established to accommodate this, again leading to a design more complex than a straightforward fixed model. Nested sets are very slow for inserts because it requires updating left and right domain values for all records in the table after the insert. This can cause a lot of database stress as many rows are rewritten and indexes rebuilt. However, if it is possible to store a forest of small trees in table instead of a single big tree, the overhead may be significantly reduced, since only one small tree must be updated. The?nested interval model?does not suffer from this problem, but is more complex to implement, and is not as well known. It still suffers from the relational foreign-key table problem. The nested interval model stores the position of the nodes as rational numbers expressed as quotients (n/d).?[1](//www.sigmod.org/publications/sigmod-record/0506/p47-article-tropashko.pdf)

變體

使用上面描述的nested set modal 在一些特定的樹遍歷操作上有性能限制。比如根據父節點查找直接子節點需要刪選子樹到一個指定的層級如下所示:

SELECT Child.Node, Child.Left, Child.Right
FROM Tree as Parent, Tree as Child
WHEREChild.Left BETWEEN Parent.Left AND Parent.RightAND NOT EXISTS (    -- No Middle NodeSELECT *FROM Tree as MidWHERE Mid.Left BETWEEN Parent.Left AND Parent.RightAND Child.Left BETWEEN Mid.Left AND Mid.RightAND Mid.Node NOT IN (Parent.Node AND Child.Node))AND Parent.Left = 1  -- Given Parent Node Left Index
復制代碼

或者:

SELECT DISTINCT Child.Node, Child.Left, Child.Right
FROM Tree as Child, Tree as Parent 
WHERE Parent.Left < Child.Left AND Parent.Right > Child.Right  -- associate Child Nodes with ancestors
GROUP BY Child.Node, Child.Left, Child.Right
HAVING max(Parent.Left) = 1  -- Subset for those with the given Parent Node as the nearest ancestor復制代碼

當查詢不止一層深度的子節點的時候,查詢將更加的復雜,為了突破限制和簡化遍歷樹,在模型上增加一個額外的字段來維護樹內節點的深度:

在這個模型中,找到指定父節點的緊跟直接子節點可以使用下面的SQL語句實現:

SELECT Child.Node, Child.Left, Child.Right
FROM Tree as Child, Tree as Parent
WHEREChild.Depth = Parent.Depth + 1AND Child.Left > Parent.LeftAND Child.Right < Parent.RightAND Parent.Left = 1  -- Given Parent Node Left Index
復制代碼

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/452883.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/452883.shtml
英文地址,請注明出處:http://en.pswp.cn/news/452883.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

互聯網商業模式:增值還是減值?

網絡可以為服務增值&#xff0c;這是人們的共識。不但是增值&#xff0c;而且是按照用戶的平方增值&#xff0c;這是梅特卡夫定律說的。 我認為&#xff0c;網絡也可以為服務減值&#xff0c;是按照服務提供商的數量的平方減值。如果按用戶增值是網絡的第一定律&#xff0c;這…

程序的鏈接方式

1 靜態鏈接 2 裝入時動態鏈接 3 運行時動態鏈接

Django中--自定義模型管理器類

BookInfo.objects.all()->objects是一個什么東西呢&#xff1f; 答&#xff1a;objects是models.Manger類的一個對象&#xff0c;是Django幫我自動生成的管理器對象&#xff0c;通過這個管理器可以實現對數據的查詢。 自定義管理器之后Django不再幫我們生成默認的objects管…

字符驅動之按鍵(四:poll機制)

1 采用之前的中斷按鍵法&#xff0c;程序會一直在read函數中死循環。2 使用了poll之后&#xff0c;在一段時間內如果有按鍵按下就會返回&#xff0c;如果沒有按鍵按下等時間到再返回。3 4 應用程序的open,read,write,poll分別對應了驅動程序的open,read,write和poll。5…

第二章 API的理解和使用

2.1.1全局命令 Key * 查看所有鍵&#xff0c;(慎用&#xff0c;會把所有鍵都遍歷一次并列出) Dbsize 查看鍵總數&#xff0c;不會遍歷所有鍵&#xff0c;只是從內置函數中讀取一個數 Exists [key] 檢查鍵是否存在 Del [key] 刪除鍵 Expire [key] [seconds] 設置鍵過期時間 Type…

java uuid 線程安全_java – 在多線程應用程序中生成相同的UUID

我使用UUID.randomUUID().toString()將一個唯一值附加到最終存儲在數據庫中的字符串,并對其具有唯一約束但是因為我的應用程序是多線程的,所以執行在UUID生成的同時發生,并且最終將相同的UUID附加到字符串并且持久性失敗.有沒有更好的方法來生成隨機字符串,即故障安全方法.我嘗…

社會生活、工作中的著名法則

社會生活中的著名法則(1)&#xff1a;馬太效應 《新約 馬太福音》中有這樣一個故事&#xff0c;一個國王遠行前&#xff0c;交給三個仆人每人一錠銀子&#xff0c;吩咐他們&#xff1a;“你們去做生意&#xff0c;等我回來時&#xff0c;再來見我。”國王回來時&#xff0c;第一…

Django中--使用redis存儲歷史瀏覽記錄

class UserInfoView(LoginRequiredMixin, View):用戶中心-信息頁def get(self, request):顯示# Django會給request對象添加一個屬性request.user# 如果用戶未登錄->user是AnonymousUser類的一個實例對象# 如果用戶登錄->user是User類的一個實例對象# request.user.is_aut…

3D虛擬試衣有望解決厘米級服裝誤差 網購服裝不再蒙

還在擔心網購服裝對實際穿著效果沒把握嗎&#xff1f;隨著京東App 6.6.3版本的更新&#xff0c;京東試試3D虛擬試衣功能正式上線&#xff0c;消費者可按照自己的身材比例創建專屬的3D模型&#xff0c;而試穿效果則可以完全依照模型來展現。據了解&#xff0c;這個系統未來還將實…

關于idea修改當前使用的git賬戶的問題

1、問題描述&#xff1a; 由于前一段時間公司遷移git&#xff0c;就是將項目代碼等遷移到另一個git服務器上&#xff0c;結果用idea從git上clone代碼的時候發現沒有指定倉庫,如下提提示 2、排查原因&#xff1a; 開始懷疑是沒有把自己加入到項目成員里面&#xff0c;經過檢查是…

分頁和分段的區別

1.頁是信息的物理單位&#xff0c;分頁是由于系統管理的需要。段是信息的邏輯單位&#xff0c;分段是為了滿足用戶的要求。 2.頁的大小固定且由系統決定&#xff0c;段的長度不固定&#xff0c;決定于用戶所編寫的程序&#xff0c;通常由編譯程序在對源程序緊進行編譯 時&…

java 修飾_Java 修飾符

摘錄自http://www.runoob.com/java/java-modifier-types.htmlJava 修飾符Java語言提供了很多修飾符&#xff0c;主要分為以下兩類&#xff1a;訪問修飾符非訪問修飾符修飾符用來定義類、方法或者變量&#xff0c;通常放在語句的最前端。我們通過下面的例子來說明&#xff1a;pu…

內存分配,任意字節對齊

有這么一道題目&#xff0c;要求按任意字節對齊分配內存&#xff0c;接口&#xff1a;char * aligned_malloc(int size, int alignment)//size 為分配的內存大小&#xff0c;alignment對齊基數&#xff08;可以為任意數&#xff09;這個在gcc庫函數里能找到源碼&#xff0c;在f…

day16-Dom提交表單以及其他

一、前言 之前我們學習的是from提交表單&#xff0c;那個是html的提交表單方式&#xff0c;現在我們用dom來提交表單&#xff0c;還有一些其他的方式 二、dom提交表單 2.1、html提交表單 說明&#xff1a;form標簽跟submit類型的input標簽結合 <body><form id"f1…

分布式文件系統FastDFS

1. 什么是FastDFS FastDFS 是用 c 語言編寫的一款開源的分布式文件系統。FastDFS 為互聯網量身定制&#xff0c; 充分考慮了冗余備份、負載均衡、線性擴容等機制&#xff0c;并注重高可用、高性能等指標&#xff0c;使用 FastDFS 很容易搭建一套高性能的文件服務器集群提供文件…

html5 下拉刷新(pc+移動網頁源碼)

本文demo下載地址&#xff1a;http://www.wisdomdd.cn/Wisdom/resource/articleDetail.htm?resourceId1071 本文實現在html5網頁中使用下拉功能自動刷新顯示更多內容, 使用jquery捕捉和處理相應的鼠標事件, 例如內容在頂部時&#xff0c;觸發下拉事件后顯示更多內容; 如內容在…

操作系統內存管理問題集錦

1. 可采用哪幾種方式將程序裝入內存?它們分別適用于何種場合? a. 首先由編譯程序將用戶源代碼編譯成若干目標模塊&#xff0c;再由鏈接程序將編譯后形成的目標模塊和所需的-庫函數鏈接在一起&#xff0c;組成一個裝入模塊&#xff0c;再由裝入程序將裝入模塊裝入內存&#x…

java同名變量在list中添加兩次_快速解決List集合add元素,添加多個對象出現重復的問題...

首先我們在new 一個對象的時候&#xff0c;對象的id是唯一確定的&#xff1b;將對象add入list中時&#xff0c;放入list中的其實是對象的引用 &#xff1b;而每次循環只是簡單的set 對象的屬性&#xff0c;set新的屬性值&#xff0c;而add進list中的對象還是同一個對象id&#…

python面試題總結(1)--語言特性

1. 談談對 Python 和其他語言的區別 答&#xff1a; Python 是一門強類型的可移植、可擴展、可嵌入的解釋型編程語言&#xff0c;屬于動態語言&#xff1b;其語法簡潔優美、功能強大無比、應用領域非常廣泛且具有強大完備的第三方庫。 &#xff08;注&#xff1a;語言有無類型…

視頻網站盈利模式與營銷策劃

在與數十家視頻網站進行信息網絡傳播權交易過程中&#xff0c;在研究視頻網站內容和盈利模式基礎上&#xff0c;綜合自己在傳統媒體和新媒體領域十幾年的策劃和營銷經驗&#xff0c;我發現&#xff1a;視頻網站的盈利模式其實早就形成多種體系&#xff0c;但是盈利之路艱難&…