我们有一个模拟树的数据库。这些数据可能会增长得相当大,也就是说很多,可能会有数百万行。 (主键实际上是bigint
,所以我想我们可能希望支持数十亿行,尽管这可能永远不会发生。
单个节点可以拥有非常多的直接子节点,更可能是它们所在的层次结构中的较高节点。我们对叶子的实际最大深度没有特定的限制,即一个人必须经过多少个节点才能到达根部,但实际上这通常不会超过几百个。通常它可能低于20。
此表中的插入非常频繁,需要具有高性能。插入的插入节点始终是叶节点,并且始终在最后一个兄弟节点之后。节点永远不会移动。删除始终作为整个子树。查找子树是在此表上进行的其他操作。它没有相同的性能要求,但我们当然希望它尽可能快。
今天,这是使用父/子模型建模的,这对于插入是有效的,但是查找子树的速度非常慢。当表变大时,这变得非常慢并且找到子树可能需要几分钟。
所以我考虑将其转换为可能在SQL Server中使用新的hierarchyid类型。但我很难弄清楚这是否合适。正如我所说,对于我们在这种情况下执行的操作,这样的树将是一个好主意。 (如果我错了,请纠正我)。
但它还指出hierarchyid的最大大小是892字节。但是,我找不到任何有关这在实践中意味着什么的信息。层次结构是如何编码的?我是否会用完hierarchyids,如果是的话,何时?
答案 0 :(得分:4)
所以我做了一些测试,并对hierarchyid
的限制得出了一些结论:
如果我运行以下代码:
DECLARE @i BIGINT = 1
DECLARE @h hierarchyId = '/'
WHILE 1=1
BEGIN
SET @h = @h.ToString() + '1/'
PRINT CONVERT(nvarchar(max), @i)
SET @i = @i+1
END
在出现错误之前,我会深入 1427 级别。由于我对每个级别使用值1
,这应该是最紧凑的树,我从中得出结论,我将永远无法创建超过 1427 等级。
但是,如果我为每个级别使用例如99999999999999
(例如/99999999999999/99999999999999/99999999999999/...
,则错误发生在 118 级别深处。似乎14位数字也是每个级别的id的最大值,因为如果我使用15位数字,它会立即失败。
因此,考虑到这一点,如果我只使用整数标识符(即不在其他节点之间插入节点等),我应该能够在我的方案中保证最多至少100级,并且在任何时候我能超过1400级吗?
答案 1 :(得分:1)
892个字节听起来不是很多,但层次结构ID在空间方面看起来非常有效。来自http://technet.microsoft.com/en-us/library/bb677290.aspx:
表示具有n个节点的树中的节点所需的平均位数取决于平均扇出(节点的平均子节点数)。对于小扇出(0-7),大小约为6 * logAn位,其中A是平均扇出。组织层次结构中的节点为100,000人,平均扇出为6级,大约需要38位。这可以舍入到40位或5个字节进行存储。
给出的计算表明它只适用于小扇出(0-7),因此很难推断更大的扇出。你说“最多可以容纳几百个孩子”。这种(极端)情况确实很危险。我不知道hierarchy_id的规范,但是在任何一个级别上节点越多,在这些892字节内树中应该具有的深度越少。
我确实在这里看到了风险,因为你(因此问题)。做一些测试。评估目标。你是从哪里搬来的?你为什么要搬家?简单还是表现?
这个问题不适合Sql。也许您应该考虑这部分程序的其他选项?