maxrecursionのシステム全体のデフォルトを変更する


12

システム全体のデフォルト値の変更方法を教えてくださいMAXRECURSION

デフォルトでは100ですが、1000などに増やす必要があります。

クエリを取得して実行するプログラムを使用しているため、クエリヒントを使用できません。残念ながら、この制限を回避することはできません。

ただし、サーバーインスタンスの管理者権限は持っています。サーバーファセットをざっと見てきましたが、クエリオプションや再帰に関連するものは何もありません。私はそこに想定している私は、システム全体のデフォルトを更新することができる場所のどこかにあることを。

何か案は?


3
100の制限はビューと関数のみであり、ストアドプロシージャを使用してローカルでオーバーライドできることを確認したかっただけですか?関数を使用する必要は特にありますか?再帰はかなり非効率的であるため、階層を1回だけウォークして、出力をテーブルに格納することもお勧めします。次に、そのテーブルを参照する関数を作成できます。どう思いますか?
wBob 2016

回答:


10

クエリの形状が共通している場合は、1つ以上のプランガイドを使用して、必要なmaxrecursionヒントを追加できる場合があります。

それらを正しくするコツがあるかもしれません。質問に特定のクエリの詳細を追加すると、それを解決できる場合があります。通常、実際にサーバーにアクセスするSQLをトレースするか、組み込みのsys.sp_get_query_templateを使用してパラメーター化されたフォームを取得し、TEMPLATEまたはOBJECT / SQLプランガイドを作成します。

詳細については、ドキュメントを参照してください。

プランガイドは、アプリケーションコードが変更されたとき、およびSQL Serverにパッチが適用されたとき、またはアップグレードされたときに再検証する必要があります。これは、通常のテストサイクルの一部にすぎません。

ガイド付きステートメントが一時テーブルを参照している場合、sys.fn_validate_plan_guideを使用したプランガイドの検証でエラーが誤って報告される可能性があることに注意してください。この質問を参照してください:

fn_validate_plan_guideを使用したプランガイドの検証で誤検知が発生する

プランガイドの成功計画ガイド失敗したプロファイラおよび拡張イベントのクラスはまた、プランガイドのアプリケーションを監視するために使用することができます。

Connectは、製品の改善提案であるSteve KassによるビューとUDFに対して100以外のMAXRECURSION制限値許可するが実装される前に廃止されました。今すぐMicrosoftで取り上げたい場合は、SQL Serverヘルプとフィードバックのオプションを参照してください。


これはイライラさせられ、質問の答えにはならず、代わりにドキュメントのうさぎの穴に私たちを埋葬します。EF Core(通常のORM)は、親のselectでラップする生のSQLステートメントを与えても、EF Coreを使用するすべてのユーザーがこの問題を抱えている場合でも、クエリを生成します。あなたの解決策は「クエリを計画する」ことです。
戦争

@戦争それは私が提供された詳細でこの特定の質問に与えることができる最良の答えです。最大の再帰ヒントを追加するために知っている唯一の方法は、「クエリの計画」とは関係のない、プランガイドと呼ばれるSQL Serverを使用することです。独自の質問がある場合は、最小限の再現可能な例を使用して個別に質問してください。
ポールホワイト9

9

関数(暗黙のETLツールの制限)を絶対に使用する必要がある場合OPTIONは、マルチステートメントテーブル値関数の一部として、たとえば次のように指定できます。

CREATE FUNCTION dbo.udf_MyFunction ( @StartID INT ) 
RETURNS @tv TABLE
(
id INT
)
AS
BEGIN

    WITH Episodes( xlevel, PersonID, EventID, EpisodeID, StartDT, EndDT ) AS (
    -- Anchor case - the first EventID for each person.
    SELECT 1 AS xlevel, PersonID, EventID, @StartID, StartDT, EndDT 
    FROM dbo.EventTable
    WHERE EventID = @StartID

    UNION ALL

    SELECT xlevel + 1, et.PersonID, et.EventID, c.EventID + 1, et.StartDT, et.EndDT
    FROM Episodes c
        INNER JOIN dbo.EventTable et ON c.PersonID = et.PersonID
            AND et.EventID = c.EventID + 1
    --WHERE c.EventID <= (@StartID + 99)
    )
    INSERT INTO @tv
    SELECT PersonID
    FROM Episodes
    OPTION ( MAXRECURSION 1000 )

    RETURN

END
GO

これは、ETLツールのようにビューにラップしたときにも機能しました。これをシステム全体で変更する方法はありませんが、再帰は効率が悪い場合があるため、これはおそらく良いことです。OPTION例のように、インラインテーブル値関数の本体内で(を使用して)クエリヒントを指定することはできません。

エピソードを受信して​​リレーショナルテーブルに出力を格納するときに、階層を1回だけ歩くようにプロセスを変更することを検討してください。ストアドプロシージャを使用してこれを行うことができるため、この制限にぶつかることはありません。

また、コードにバグがある可能性があると思います。CTEがpersonIdに参加し、eventIdで再帰する場合、eventId 101が重複して2回表示されると思います。おそらく私はあなたのコードを誤って解釈したので、あなたの考えを知らせてください。

HTH


「OPTIONS」パラメータはステートメントレベルで適用する必要があり、問題のステートメントは関数の呼び出しなので、これは機能しません。これは例外を返します。
戦争

0

このトピックからインスピレーションを得ました。

これは、問題を解決するために私がやったことです。

CREATE FUNCTION MySchema.udf_MyFunction(@StartID INT) 
RETURNS TABLE 
AS RETURN
WITH
Episodes(PersonID, EventID, EpisodeID, StartDT, EndDT) AS (
  -- Anchor case - the first EventID for each person.
  SELECT PersonID, EventID, @StartID, StartDT, EndDT 
  FROM MySchema.EventTable
  WHERE EventID = @StartID
UNION ALL
  SELECT
    ...
  WHERE
    EventID <= (@StartID + 99)
)
SELECT * FROM Episodes

次に、この関数を次のように呼び出します。

WITH
Episodes AS (
  SELECT * FROM MySchema.udf_MyFunction(1)
UNION ALL
  SELECT * FROM MySchema.udf_MyFunction(101)
UNION ALL
  SELECT * FROM MySchema.udf_MyFunction(201)
-- ...
UNION ALL
  SELECT * FROM MySchema.udf_MyFunction(901)
)
SELECT * FROM Episodes

このようにして、私のCTEロジックを繰り返す必要がなくなり、パフォーマンスの点で余分に支払う必要がなくなります。このように行わなければならないのは面倒ですが、私はそれと共存できます。


3
これが再帰問題をどのように解決するかはわかりません。関数の呼び出しは再帰的ではありません。
ypercubeᵀᴹ

@ypercubeᵀᴹ-省略記号があるところにCTEの再帰ビットが入ります-特定の再帰ロジックは問題に実際には関係ありませんが、CTEは実際には再帰的であると想定できます。where省略記号の後の節は、関数パラメーターを制約として使用することにより、あまりにも多くの再帰が発生するのを防ぎます。ただし、CTEの定義の後には説明があるはずです。追加します。
carl.anderson

3
CTEが再帰的であることをよく理解しています。問題は、呼び出し(関数呼び出し)が再帰的でないことです。たとえば、EventID=1(および101,201、... 901)を開始点(行)として関数を呼び出します。ただし、元のクエリ(MAXRECURSION = 100000000で実行された場合)は、EventID=101(および201、..、901)の行にアクセスできません。したがって、2つのクエリ(オリジナルとソリューション)は異なる結果を返す可能性があります(最初の行が101で、2番目の行がはい)。あなたのソリューションは、(再び異なる)の結果で2回連続が含まれるであろうように、またはそれは、101が、ステップ100の前を訪問するかもしれない
ypercubeᵀᴹ

2
もちろん、データが連続したEventID値(1,2、、3 ...、99,100,101、..)に関連付けられている場合を除きます。その場合、再帰CTEはまったく必要ありません。
ypercubeᵀᴹ

これは、特定のDMSパスからツリーを行セットとして取得するなど、未知の深さの問題をどのように解決しますか?
戦争
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.