Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 分层SQL数据(递归CTE与层次ID与闭包表)_Sql Server_Common Table Expression_Recursive Query_Hierarchyid_Transitive Closure Table - Fatal编程技术网

Sql server 分层SQL数据(递归CTE与层次ID与闭包表)

Sql server 分层SQL数据(递归CTE与层次ID与闭包表),sql-server,common-table-expression,recursive-query,hierarchyid,transitive-closure-table,Sql Server,Common Table Expression,Recursive Query,Hierarchyid,Transitive Closure Table,我在SQL Server数据库中使用了一组分层数据。存储数据时,guid作为主键,parentGuid作为指向对象直接父对象的外键。我最常通过WebApi项目中的实体框架访问数据。为了使情况更加复杂,我还需要基于此层次结构管理权限,以便应用于父级的权限应用于其所有子级。我的问题是: 我已经找遍了所有地方,无法决定哪一个最适合处理这种情况。我知道我有以下选择 我可以创建递归CTE,公共表表达式(也称为RCTE)来处理分层数据。这似乎是正常访问最简单的方法,但我担心它在用于确定子对象的权限级别时可能

我在SQL Server数据库中使用了一组分层数据。存储数据时,guid作为主键,parentGuid作为指向对象直接父对象的外键。我最常通过WebApi项目中的实体框架访问数据。为了使情况更加复杂,我还需要基于此层次结构管理权限,以便应用于父级的权限应用于其所有子级。我的问题是:

我已经找遍了所有地方,无法决定哪一个最适合处理这种情况。我知道我有以下选择

  • 我可以创建
    递归CTE
    ,公共表表达式(也称为RCTE)来处理分层数据。这似乎是正常访问最简单的方法,但我担心它在用于确定子对象的权限级别时可能会很慢
  • 我可以在表中创建一个
    hierarchyId
    数据类型字段,并使用SQL Server提供的函数,如
    get祖先()
    isdescendatof()
    ,等等。这似乎可以使查询变得相当简单,但似乎需要一个相当复杂的插入/更新触发器,以通过插入和移动保持hierarchyId字段的正确性
  • 我可以创建一个
    闭包表
    ,它将存储表中的所有关系。我想象它是这样的:父列和子列,每个父->子关系都将被表示。(即1->2->3将在数据库中表示为1-2、1-3、2-3)。缺点是,这需要insert、update和delete触发器,即使它们相当简单,而且这种方法会生成大量记录
  • 我试过到处搜索,但在这三种方法之间找不到任何建议


    PS我也愿意接受这个问题的任何替代解决方案

    我已经使用了这三种方法。这主要是一个品味的问题

    我同意表中具有父子关系的层次结构是最简单的。移动子树很简单,并且很容易用CTE编码递归访问。只有当您有非常大的树结构并且经常访问分层数据时,性能才会成为一个问题。在大多数情况下,当表上有正确的索引时,递归CTE非常快

    闭包表更像是上述内容的补充。查找给定节点的所有子代速度非常快,您不需要CTE,只需要一个额外的连接,所以这很好。是的,记录的数量会爆炸,但我认为它不超过深度为N的树的节点数量的N-1倍(例如,深度为5的三级树在仅存储父子关系时需要1+3+9+27+81=121个连接,而闭包表则需要1+3+(9*2)+(27*3)+(81*4)=427个连接)。此外,闭包表记录非常窄(至少只有2个整数),几乎不占用任何空间。在层次结构中插入新记录时,生成要插入到闭包表中的记录列表需要少量开销

    我个人喜欢HierarchyId,因为它真正结合了上述两种功能的优点,即紧凑的存储和闪电般的快速访问。一旦设置好,查询就很容易,占用的空间也很小。正如您所提到的,移动子树有点棘手,但它是可管理的。不管怎样,在层次结构中真正移动子树的频率是多少?您可以找到一些链接,这些链接将建议一些方法,例如:


    我发现hierarchyId的主要缺点是学习曲线。如何使用它不像其他两种方法那么明显。我曾与一些非常聪明的SQL开发人员合作,他们经常会在这方面遇到困难,因此你最终会遇到一两位常驻专家,他们必须回答其他人提出的问题。

    请用你正在使用的SQL Server版本标记你的问题。您的查询是倾向于从子查询到父查询,还是相反?一个RCTE在树上为一个单独的孩子跟随父母链接应该不会太糟糕。对于所有的孩子来说,走另一条路会变得很慢。我现在不能检查版本,但稍后会检查。我认为这不是2008年就是更新。很可能我会更多地得到父母的孩子,而不是孩子的父母。我无法添加另一个标记,但它是SQL Server 2008 r2。我在初次尝试hierarchyId时遇到的两个缺点是,第一,在插入/更新触发器中处理批量插入/更新,第二,在C#through实体框架中使用hierarchyId表。关于处理这两个问题,你有什么建议或信息吗?此外,这个答案非常有帮助,但在我选择它之前,我将稍等片刻,以鼓励其他可能有帮助信息的人。在Analysis Services中尝试使用这些关系时,无论选择何种方法来表示它们,都会遇到另一个缺点。在AnalysisServices中,自连接、循环和hierarchyid都是不受支持的,这意味着您最终必须执行两种变通方法之一;(1) 创建展平视图以表示以这种方式存储的维度,或者(2)使用SSI将维度展平到BI数据库(星形或雪花模式)中。每当向层次结构中添加新项时,这两种解决方案都需要维护。