5

大きなツリーで再帰的な cte を使用するクエリがビューにあり、パラメータではなくハードコードされた数値でクエリを実行するとうまく機能します。この再帰的な cte クエリを最適化する計画を SQL Server に強制的に使用させることはできますか? どんなアイデアでも大歓迎です。

再帰 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

パラメーターを使用したビューのクエリは、ビュー全体をクエリし、ツリーが大きすぎるために終了しないようにフィルター処理するように見えます-最大再帰エラーが発生します:

DECLARE @TopLevelEnt int
SET @TopLevelEnt = 187317;
select * from adams_test_view
WHERE eqId = @TopLevelEnt

これが計画です(インデックス名についてはお詫びします):

  |--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)

ハードコードされた値を使用して同じクエリを実行すると、正常に返されます。

クエリ:

SELECT * FROM adams_test_view
WHERE eqId = 187317

予定:

  |--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)

エンティティ pk の再編成と実行を試みましsp_updatestatsたが、違いはありませんでした。

また、ヒントの最適化を追加しようとしましたが、それを拾っていないようです。

DECLARE @TopLevelEnt int
SET @TopLevelEnt = 187317;
select * from adams_test_view
WHERE eqId = @TopLevelEnt
OPTION (OPTIMIZE FOR (@TopLevelEnt = 187317))

これを SQL Server Management Studio Express 2008 R2 の SQL Server 2005 Express データベースで実行しています

ヒントやハッカーをいただければ幸いです。

4

1 に答える 1

1

ビューは最初にすべてのものを返し、次に変数を見て、それに応じてフィルタリングするため、表示されるのは正常です。ハードコーディングされている場合、適用するフィルターを最初から認識しているため、別のプランを選択します。

cteの上部選択にフィルターを使用して、インラインテーブル値関数で同じことを試しましたか?

于 2015-08-03T10:15:45.057 に答える