HierarchyId is documented 非常紧凑
表示一个节点所需的平均位数
具有 n 个节点的树取决于平均扇出(平均
节点的子节点)。对于小扇出(0-7),大小约为
6*logAn 位,其中 A 是平均扇出。一个节点
100,000 人的组织层次结构,平均扇出数为 6
级别大约需要 38 位。这四舍五入到 40 位或 5 个字节,
用于存储。
因此很明显,它可以在一个字节中容纳多个级别。
内部格式没有记录,但有人has previously investigated this(当我查看原始页面时,由于原始页面没有加载,所以返回机器链接)。
免责声明:来源本身是非权威的,只是从价值检查中推断出来的,我可能在下面引入了进一步的错误!
下面给出了一些相当简单的例子
WITH HierarchyIdStrings(path) As
(
SELECT '/' UNION ALL
SELECT '/0/' UNION ALL
SELECT '/1/' UNION ALL
SELECT '/1/1/' UNION ALL
SELECT '/1.1/' UNION ALL
SELECT '/2/' UNION ALL
SELECT '/98/'
)
SELECT HierarchyId::Parse(path) AS HierarchyId, path,
bin,
trimmed_bin = LEFT(bin, 1 + LEN(bin) - CHARINDEX('1', REVERSE(bin)))
FROM HierarchyIdStrings
CROSS APPLY(SELECT CONVERT(VARCHAR(1784), CAST(HierarchyId::Parse(path) AS VARBINARY(892)), 2)) V1(hex)
CROSS APPLY (SELECT
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
hex,
'0', '0000'),'1', '0001'),'2', '0010'),'3', '0011'),
'4', '0100'),'5', '0101'),'6', '0110'),'7', '0111'),
'8', '1000'),'9', '1001'),'A', '1010'),'B', '1011'),
'C', '1100'),'D', '1101'),'E', '1110'),'F', '1111') ) V2(bin)
ORDER BY HierarchyId
结果
+-------------+-------+--------------------------+--------------------+
| HierarchyId | path | bin | trimmed_bin |
+-------------+-------+--------------------------+--------------------+
| 0x | / | | |
| 0x48 | /0/ | 01001000 | 01001 |
| 0x58 | /1/ | 01011000 | 01011 |
| 0x5AC0 | /1/1/ | 0101101011000000 | 0101101011 |
| 0x62C0 | /1.1/ | 0110001011000000 | 0110001011 |
| 0x68 | /2/ | 01101000 | 01101 |
| 0xE02540 | /98/ | 111000000010010101000000 | 111000000010010101 |
+-------------+-------+--------------------------+--------------------+
0x58 的二进制表示是01011000,但尾随零应该被忽略,所以我们只需要关心 5 位。 01011.
链接的文章假设初始前缀 01 是为组件 /0/ ... /3/ 保留的,因此它知道它只需要为该组件再读取三个位。接下来的两位是值本身,最后一位是1,因为这不是虚线组件。
/1/1/ 的表示只是将其中两个连接在一起。
1.1 的表示将1 添加到01011 以得到01100,然后将01011 连接到其末尾。
/98/ 更复杂。这给出了111000000010010101 的位串。
链接文章指出/80/ 到/1103/ 的范围将具有前缀1110 并采用1110aaa0zzz0y1xxx1 形式
-
aaa = 000(十进制0)
-
zzz = 001(十进制1)
-
y = 0(十进制0)
-
xxx = 010(十进制2)
1x + 8y + 16z + 80 = 2 + 0 + 16 + 80 = 98
组件也有可能是负数。如果对此感兴趣,请参阅链接文章!