1

我目前有一个包含自联接的查询,用于从使用嵌套集模型存储公司组织信息的表中查询员工的所有直接和间接经理。在此 SQL 表示法中,以冒号开头的数字(例如:1)是变量:

select parent.empid, parent.depth from RelationshipMgr as node join
RelationshipMgr as parent on node.lft between parent.lft and parent.rgt
and node.empid = :1 order by parent.lft

通过添加加入条件或 where 子句(附带问题:哪个更快?),我可以轻松地仅返回员工之上n级的经理的 ID 。parent.depth = node.depth - :2

问题:我正在尝试将此查询转换为视图,但运气不佳。问题是我的大部分或所有变量都在我的查询的连接条件中。我目前最好的计划是将这些部分分成列,然后我可以在查询视图时使用 where 子句,例如:

select node.EmpID, parent.empid as MgrID, parent.depth as MgrDepth,
node.depth - parent.depth as MgrRelativeAltitude from RelationshipMgr as node
join RelationshipMgr as parent on node.lft between parent.lft and parent.rgt

您可以看到我必须发明该MgrRelativeAltitude列才能找到比员工高n级的经理的 ID,但这并不是最大的问题。我担心这会产生严重的性能问题,因为 SQL Server 似乎是按照连接条件指定的方式进行完全连接,然后通过 where 子句对其进行过滤,而不是智能地使用 where 子句来限制连接。 有没有更好的方法来创建视图?我是否应该将其保留为查询并忘记制作视图?我会通过将其设为存储过程而不是视图来获得什么吗?

请不要说“过早的优化是邪恶的”……这并不为时过早。我要替换的实现使用了诸如混蛋邻接列表之类的东西,该列表具有将员工与其直接和间接经理中的任何一个相关联的记录……最坏的情况是 O(n^2) 记录,并且可以预见地遇到严重的性能问题时我们在层级中有超过 300,000 名员工。我的新嵌套集实现将缓解这些性能问题,除了这个查询...如果您select *对建议的视图执行操作,结果将与我尝试替换的旧表几乎相同,这让我很担心非常。

4

1 回答 1

0

您正在尝试确定非相邻节点的层次关系。正如您所发现的,这是一个相对昂贵的运行时计算、视图或常规查询。相反,如果经常运行,我建议创建所谓的桥表- 作为通过触发器更新的真实表或作为 SQL Server 2005+ 中的索引视图(尽管尚未尝试过索引视图方法)。值得注意的是,与邻接表相比,嵌套集提供了更长的读取时间。

权衡是一个表的行数明显多于源表,因为它有效地表示了所有节点之间的关系,当它更新任何时间节点被添加、删除或父 ID 更改时会减慢写入速度。作为回报,您可以索引它并实现快速检索。如果更新网桥证明存在瓶颈,则优化是通过存储过程访问它,其中网桥用作频繁运行的输入组合的缓存,但在运行时计算不常见的情况。您需要评估底层节点表的读取与写入频率来做出决定。

此处提供了在 RDBMS 中表示分层数据的选项的概述

于 2011-02-02T15:29:24.613 回答