是否有可能强制SQL Server使用我想要优化递归cte查询的计划

Ada*_*ler 5 sql-server performance sql-server-2005 recursive-query

我在一个视图中使用一个大型树上的递归cte查询,当使用硬编码但不使用参数查询时,该查询效果很好.是否有可能强制SQL Server使用我想要优化此递归cte查询的计划?任何想法,将不胜感激.

以下是递归CTE的视图 - 它检索给定实体下的所有节点:

CREATE VIEW adams_test_view AS
WITH eq_mi_cte(miId, eqId, miName, miCode) AS
    (SELECT ent.id, ent.id, ent.name, ent.code
    FROM entity ent
    UNION ALL
    SELECT e.id, eq_mi_cte.eqid, e.name, e.code
    FROM entity e
    INNER JOIN eq_mi_cte ON e.pid = eq_mi_cte.miid)
SELECT * FROM eq_mi_cte
Run Code Online (Sandbox Code Playgroud)

带有参数的视图上的查询似乎查询整个视图然后过滤它,因为树太大而从未完成 - 我们得到最大的递归错误:

DECLARE @TopLevelEnt int
SET @TopLevelEnt = 187317;
select * from adams_test_view
WHERE eqId = @TopLevelEnt
Run Code Online (Sandbox Code Playgroud)

这是计划(我对索引名称的应用):

  |--Filter(WHERE:([Recr1009]=[@TopLevelEnt]))
       |--Index Spool(WITH STACK)
            |--Concatenation
                 |--Compute Scalar(DEFINE:([Expr1012]=(0)))
                 |    |--Index Scan(OBJECT:([local_dbname].[dbo].[Entity].[EntityParentId] AS [ent]))
                 |--Assert(WHERE:(CASE WHEN [Expr1014]>(100) THEN (0) ELSE NULL END))
                      |--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1014], [Recr1004], [Recr1005], [Recr1006], [Recr1007]))
                           |--Compute Scalar(DEFINE:([Expr1014]=[Expr1013]+(1)))
                           |    |--Table Spool(WITH STACK)
                           |--Index Seek(OBJECT:([local_dbname].[dbo].[Entity].[EntityParentId] AS [e]), SEEK:([e].[PId]=[Recr1004]) ORDERED FORWARD)
Run Code Online (Sandbox Code Playgroud)

现在,当我使用硬编码值执行相同的查询时,它返回正常:

查询:

SELECT * FROM adams_test_view
WHERE eqId = 187317
Run Code Online (Sandbox Code Playgroud)

计划:

  |--Index Spool(WITH STACK)
       |--Concatenation
            |--Compute Scalar(DEFINE:([Expr1012]=(0)))
            |    |--Clustered Index Seek(OBJECT:([local_dbname].[dbo].[Entity].[PK__Entity__2E1BDC42] AS [ent]), SEEK:([ent].[Id]=(187317)) ORDERED FORWARD)
            |--Assert(WHERE:(CASE WHEN [Expr1014]>(100) THEN (0) ELSE NULL END))
                 |--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1014], [Recr1004], [Recr1005], [Recr1006], [Recr1007]))
                      |--Compute Scalar(DEFINE:([Expr1014]=[Expr1013]+(1)))
                      |    |--Table Spool(WITH STACK)
                      |--Index Seek(OBJECT:([local_dbname].[dbo].[Entity].[EntityParentId] AS [e]), SEEK:([e].[PId]=[Recr1004]) ORDERED FORWARD)
Run Code Online (Sandbox Code Playgroud)

我尝试重新组织实体pk,并且运行sp_updatestats但没有任何区别.

还尝试添加一个优化提示,但似乎并没有提起它,例如.

DECLARE @TopLevelEnt int
SET @TopLevelEnt = 187317;
select * from adams_test_view
WHERE eqId = @TopLevelEnt
OPTION (OPTIMIZE FOR (@TopLevelEnt = 187317))
Run Code Online (Sandbox Code Playgroud)

我在SQL Server Management Studio Express 2008 R2的SQL Server 2005 Express数据库上运行它

任何提示或hackery将不胜感激.

Jul*_*eur 1

您看到的是正常的,因为视图首先返回所有内容,然后查看变量并相应地进行过滤。当它被硬编码时,它会选择另一个计划,因为它从一开始就知道要应用哪个过滤器。

您是否尝试过使用内联表值函数执行相同的操作,并在 cte 的上部选择上使用过滤器?