Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.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 优化CTE以在父子层次结构的特定级别返回子体_Sql Server_Sql Server 2008_Query Optimization_Common Table Expression - Fatal编程技术网

Sql server 优化CTE以在父子层次结构的特定级别返回子体

Sql server 优化CTE以在父子层次结构的特定级别返回子体,sql-server,sql-server-2008,query-optimization,common-table-expression,Sql Server,Sql Server 2008,Query Optimization,Common Table Expression,我在SQLServer2008R2中定义了一个简单的临时表,表示父子关系。可以有多个层次结构(例如,最多10层)。我使用CTE在我的表中查找子代,这些子代在后代层次结构中至少处于第3级,换句话说,至少有一个父母和一个祖父母 以下是一个脚本,用于演示我正在使用的设置和CTE: set nocount on create table #linkage(entity_key bigint, parent_key bigint) --alter table #linkage add foreign ke

我在SQLServer2008R2中定义了一个简单的临时表,表示父子关系。可以有多个层次结构(例如,最多10层)。我使用CTE在我的表中查找子代,这些子代在后代层次结构中至少处于第3级,换句话说,至少有一个父母和一个祖父母

以下是一个脚本,用于演示我正在使用的设置和CTE:

set nocount on
create table #linkage(entity_key bigint, parent_key bigint)
--alter table #linkage add foreign key (parent_key) references #linkage(entity_key)

insert into #linkage values(1, 1), (2, 2), (3, 3), (4, 1), (5, 4), (6, 5)
print 'all data:' select * from #linkage

print 'level 3+ descendents:' 
;with r(entity_key, parent_key, level) as
(
    select entity_key, parent_key, 1
        from #linkage
        where entity_key = parent_key
    union all
    select p.entity_key, r.parent_key, r.level + 1
        from #linkage p
        inner join r on p.parent_key = r.entity_key 
        where p.entity_key <> r.entity_key
)
select entity_key, parent_key as ultimate_parent_key
from r
where r.level > 2
问题是我需要它来处理大型数据集。当我在1200万行上运行这个程序时,需要3分钟才能完成,我希望能显著减少这一点

我尝试过创建聚集索引和非聚集索引的各种组合(entity_key)、(entity_key、parent_key)等等,但似乎没有任何帮助(实际上,有些似乎会减慢速度)

以下是针对1200万行(无索引)的执行计划:

  |--Filter(WHERE:([Recr1014]>(2)))
       |--Index Spool(WITH STACK)
            |--Concatenation
                 |--Compute Scalar(DEFINE:([Expr1015]=(0)))
                 |    |--Compute Scalar(DEFINE:([Expr1004]=(1)))
                 |         |--Table Scan(OBJECT:([tempdb].[dbo].[#linkage]), WHERE:([tempdb].[dbo].[#linkage].[entity_key]=[tempdb].[dbo].[#linkage].[parent_key]))
                 |--Assert(WHERE:(CASE WHEN [Expr1017]>(100) THEN (0) ELSE NULL END))
                      |--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1017], [Recr1008], [Recr1009], [Recr1010]))
                           |--Compute Scalar(DEFINE:([Expr1017]=[Expr1016]+(1)))
                           |    |--Table Spool(WITH STACK)
                           |--Compute Scalar(DEFINE:([Expr1011]=[Recr1010]+(1)))
                                |--Filter(WHERE:([tempdb].[dbo].[#linkage].[entity_key] as [p].[entity_key]<>[Recr1008]))
                                     |--Index Spool(SEEK:([p].[parent_key]=[Recr1008]))
                                          |--Table Scan(OBJECT:([tempdb].[dbo].[#linkage] AS [p]))
|--Filter(其中:([Recr1014]>(2)))
|--索引滑阀(带堆栈)
|--串联
|--计算标量(定义:([Expr1015]=(0)))
||--计算标量(定义:([Expr1004]=(1)))
||--表扫描(对象:([tempdb].[dbo].[dbo].[linkage]),其中:([tempdb].[dbo].[linkage].[entity#key]=[tempdb].[dbo].[linkage].[parent#key]))
|--断言(其中:(当[Expr1017]>(100)然后(0)否则为空结束时)
|--嵌套循环(内部联接,外部引用:([Expr1017]、[Recr1008]、[Recr1009]、[Recr1010]))
|--计算标量(定义:([Expr1017]=[Expr1016]+(1)))
||——工作台滑阀(带堆叠)
|--计算标量(定义:([Expr1011]=[Recr1010]+(1)))
|--过滤器(其中:([tempdb].[dbo].[链接].[entity_key]作为[p].[entity_key][Recr1008]))
|--索引假脱机(SEEK:([p].[parent_key]=[Recr1008]))
|--表扫描(对象:([tempdb].[dbo].[链接]作为[p]))
以下是XML格式的相同计划,以防您陷入这种情况:

我还应该注意,这个盒子有12个CPU,所以如果有某种方法可以引入一些并行性,那么这可能会有所帮助


有谁能推荐一种方法来加速此过程吗?

您是否尝试过在
父项上建立索引,并将
实体项作为包含列添加

将根节点标记为空父节点,而不是指向它们自己,应该会有帮助:

declare @linkage table (entity_key bigint, parent_key bigint null) 

insert into @linkage values
  (1, NULL), (2, NULL), (3, NULL), (4, 1), (5, 4), (6, 5), (7, 3), (8, 7), (9, 5) 

;with r(entity_key, immediate_parent, root, level) as 
(
  -- Faster search for NULL to find roots.
  select entity_key, entity_key as immediate_parent, entity_key as root, 1 
    from @linkage 
    where parent_key is NULL
  union all
  -- No WHERE clause needed.
  select p.entity_key, r.entity_key, r.root, r.level + 1 
    from r inner join
      @linkage as p on p.parent_key = r.entity_key  
) 
select *
  from r

出于好奇,在您的环境中,3分钟的运行时间缩短到了什么程度?大约2:30,包括构建索引所需的额外时间。
declare @linkage table (entity_key bigint, parent_key bigint null) 

insert into @linkage values
  (1, NULL), (2, NULL), (3, NULL), (4, 1), (5, 4), (6, 5), (7, 3), (8, 7), (9, 5) 

;with r(entity_key, immediate_parent, root, level) as 
(
  -- Faster search for NULL to find roots.
  select entity_key, entity_key as immediate_parent, entity_key as root, 1 
    from @linkage 
    where parent_key is NULL
  union all
  -- No WHERE clause needed.
  select p.entity_key, r.entity_key, r.root, r.level + 1 
    from r inner join
      @linkage as p on p.parent_key = r.entity_key  
) 
select *
  from r