我目前有一个包含自联接的查询,可以使用nested sets model从存储公司组织信息的表中查询员工的所有直接和间接经理。在此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
通过将parent.depth = node.depth - :2
添加到连接条件或where子句(旁边问题:哪个更快?),我可以简单地只返回员工 n 级别的ID。
问题:我正在尝试将此查询转换为视图,而且我没有太多运气。问题是我的大部分或全部变量都在我的查询的连接条件中。我目前最好的计划是将这些部分分解为列,然后我可以在查询视图时使用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 *
,结果将与我试图替换的旧表几乎相同,这非常关心我。
答案 0 :(得分:0)
您正在尝试确定非相邻节点的层次关系。正如您所发现的,这是一个相对昂贵的运行时计算,视图或常规查询。相反,如果频繁运行,我建议创建所谓的bridge table - 作为通过触发器更新的真实表或作为SQL Server 2005+中的索引视图(尽管尚未尝试索引视图方法) 。注意到,与邻接列表相比,嵌套集提供了更好的读取时间。
权衡是一个包含明显多于源的行的表,因为它有效地表示所有节点之间的关系,这会降低写入速度,因为它会随着节点的添加,删除或父ID的更改而更新。作为回报,您可以将其编入索引并实现快速检索时间。优化,如果更新网桥证明瓶颈是通过存储过程访问它,其中网桥用作频繁运行的输入组合的缓存,但在运行时计算不频繁的情况。您需要评估基础节点表的读取与写入频率以进行确定。
An overview of options for representing hierarchical data in a RDBMS is available here