看到网上很多文章吐槽,邻接表模型用递归获取祖先节点 /后代节点,导致性能很差。而用闭包表就能空间换时间,很快获取。
可是我看着闭包表的结构,没搞懂它是如何走索引,来快速获取祖先节点 /父节点 /子节点的。
引入一个实际例子说吧。假设闭包表结构为:(简化,后续用 节点指代的名称
代替 节点 ID
)
CREATE TABLE 闭包表 (
祖先节点 ID INT,
后代节点 ID INT,
这俩节点距离 INT,
PRIMARY KEY (祖先节点 ID, 后代节点 ID)
);
现有一张约 66W 行数据的 5 级地区表,各级数量为:*(参考自 中华人民共和国行政区划(五级))*
省 | 市 | 区 | 街 | 村 |
---|---|---|---|---|
31 | 342 | 2990 | 41356 | 618134 |
那么,建立的闭包表的行数量为:
1*1 (根, 根) + 31*2 (根, 省), (省, 省) + 342*3 + 2990*4 + 41356*5 + 618134*6 = 3928633 行
网上很多的 SQL
是这样的:
SELECT 后代节点 FROM 闭包表 WHERE 祖先节点 = '根节点' AND /* 缺失:后代节点 = ? AND */ 距离 = 1
可是,根据最左匹配原则,距离 = 1
是无法利用的,所以上述 SQL
要扫描 66W 行(每个地区都有到根节点的记录),才能获得结果??
网上的 SQL
:
SELECT 祖先节点 FROM 闭包表 WHERE /* 缺失:祖先节点 = ? AND */ 后代节点 = '杭州' AND 距离 = 1
根据最左匹配原则,利用不了索引,所以上述 SQL
要扫描 390W 行,才能获得“杭州”的父节点??
网上的 SQL
:
SELECT 祖先节点 FROM 闭包表 WHERE /* 缺失:祖先节点 = ? AND */ 后代节点 = '...' ORDER BY 距离 DESC
同理,这也是要扫描 390W 行,才能得到结果??
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.