回答

收藏

处理数据库中的层次结构数据

技术问答 技术问答 259 人阅读 | 0 人回复 | 2023-09-14

我很好奇,关于数据库设计,什么是处理层次结构的最佳方法(最佳实践)。这是我通常如何处理它们的一个小例子。
, [, @! a, Y' q6 f0 D1 p+ P节点表0 f9 k+ k7 V2 Z( Q
NodeId int PRIMARY KEY
3 c. Q' g" o8 S! j: a5 ?NodeParentId int NULL# c; P  N2 e! p, R
DisplaySeq int NOT NULL# W2 o5 @8 |2 `' L0 n; ~
Title nvarchar(255)
, a1 q8 l, ]  m8 a8 o0 j祖先表
) V* s9 e5 ?9 ~" u3 Z* ]% w+ UNodeId int
; g5 x, j( A4 ?  y7 _) c9 p2 {# `, [AncestorId int# W8 I# Z1 V* ]. B
Hops int& v. R  S( g3 v3 r2 F: x
在NodeId,AncestorId,Hops上具有索引5 e% U6 m3 T0 d- F" K6 M% v
表格如下所示:
6 C* Z" z3 D* X. m节点表) p- R/ n0 r5 v5 _+ c+ T
NodeId    NodeParentId    DisplaySeq    Title
4 }7 x! q+ z7 g# C$ j# R1         NULL            1             'Root'
. c: p/ `9 g4 y' V4 c. ]9 J2         1               1             'Child 1'' c. {9 k7 }: {( |% I: ^
3         1               2             'Child 2'4 K7 w. g8 f2 b! ?1 I# f& {) A
4         2               1             'Grandchild 1'
& h6 Q2 {6 E; E" f4 H5         2               2             'Grandchild 2'/ ?( _, F/ Q; s0 y4 N$ x
祖先表
1 h. V6 j: @5 E0 ^" |% F: o4 CNodeId    AncestorId    Hops
3 J+ k7 c$ @5 N, D1         NULL          0
* x( D. P; y5 |2 t( H. {1         1             07 K# f. ], v+ i& W% E' ^
2         1             1+ Z7 M1 Z( T6 n+ \0 m" C; z& b
2         2             09 W# U# t& c: a
3         1             1
# [. d, J# ?8 Y! l3         3             0# @$ I  X6 a3 k
4         1             2& a+ @- U) i3 Z$ p
4         2             1
4 D7 |6 V5 C+ \, |* z7 F4         4             0
$ g$ a7 q" r) Z6 a5         1             2  _9 o. f  P: N& K  D7 K& a
5         2             1. J: t' {* ?# a! w
5         5             0
: Z/ U1 Z" G# k3 w8 }1 a通过这种设计,我发现在大型层次结构中,通过加入AncestorId = target/ h' j% l& D: d+ M% T: m
NodeId的Ancestor表,可以非常快速地获得层次结构的整个部分,例如:$ k+ T; `4 y: Q* o8 ]
SELECT *
  Z0 R, ]  T! E7 U* x$ n" DFROM Node n
, ^6 g  \/ H1 {/ _; _7 E! Z. zINNER JOIN Ancestor a on a.NodeId=n.NodeId, C7 h' B' _" I" q; g4 m( R
WHERE a.AncestorId = @TargetNodeId
5 d2 ^2 P, e% w6 g/ y也很容易找到直系孩子7 T- Q* ^! r6 w* V$ Q
SELECT *, p! w+ }- K; M: c& O  W
FROM Node n
1 g- {# X) }* o9 e- x- @0 o! WINNER JOIN Ancestor a on a.NodeId=n.NodeId8 q$ S6 S( N( \; N+ _/ W, Z
WHERE a.AncestorId = @TargetNodeId( C1 O& f4 _: x- A
AND Hops = 1
  T7 ^# G6 m5 g/ T/ r4 x我有兴趣知道您可能还针对此类事情使用了哪些其他解决方案。以我的经验,层次结构可能会变得很繁琐,而任何优化其检索的方法都非常重要。
. l2 b/ F5 q2 H" |" J2 D8 Z               
4 }4 H( B6 x  A8 x7 \- Y) U解决方案:! b) C  x0 f. {1 i; M
               
" f  E( O8 S* V# ~  x1 R3 d& v4 e# `( b/ c. h+ w" \

' A- @5 T/ c0 p7 l3 c5 V                正如MarkusQ和n8wrl所指出的那样,Joe  i2 w$ B, `& H: K' q5 A) R/ w
Celko在这方面有一些不错的东西。我要补充一点,有多种方法可以对层次结构进行建模(Joe的书包含了许多我相信的内容,而不仅仅是他认为“最好”的一种方法)。您的最终决定将希望考虑您自己的特定需求。对它进行建模的一些不同方法更适合于写密集型操作,而其他一些方法则适合于频繁或快速地上下读取层次结构。只需记住您的系统将使用它做什么。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则