更改系统范围内的 maxrecursion 默认值

car*_*son 12 sql-server configuration recursive

如何更改系统范围的默认值MAXRECURSION

默认情况下它是 100,但我需要将它增加到 1000 之类的东西。

我无法使用查询提示,因为我正在使用一个程序来获取我的查询并为我执行它,而且我无法绕过这个限制,不幸的是。

但是,我确实拥有服务器实例的管理员权限。我已经浏览了服务器方面,但我没有看到任何与查询选项或递归相关的内容。我认为必须有一个地方可以更新系统范围的默认值。

有任何想法吗?

Pau*_*ite 10

如果您的查询具有共同的形状,您可以使用一个或多个计划指南添加所需的 maxrecursion 提示。

可以有一个诀窍让他们正确。如果您在问题中添加了特定的查询详细信息,我们或许能够为您解决这个问题。通常,您会跟踪实际访问服务器的 SQL,或使用内置过程sys.sp_get_query_template获取参数化表单,然后创建 TEMPLATE 和/或 OBJECT/SQL 计划指南。

有关更多信息,请参阅文档:

每当应用程序代码更改时,以及修补或升级 SQL Server 时,都需要重新验证计划指南。这应该只是您正常测试周期的一部分。

请注意,如果引导语句引用临时表,则使用sys.fn_validate_plan_guide 的计划指南验证可能会错误地报告失败。看到这个问题:

使用 fn_validate_plan_guide 进行计划指南验证会产生误报

计划指南成功计划指南不成功的探查和扩展事件类也可以用来监测计划指南应用程序。

Steve Kass提出的产品改进建议允许 MAXRECURSION 限制值不是 100 的视图和 UDF之前,Connect 已停用。如果您想立即与 Microsoft 合作,请参阅SQL Server 帮助和反馈中的选项。


wBo*_*Bob 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
Run Code Online (Sandbox Code Playgroud)

正如您建议的 ETL 工具所做的那样,当包裹在视图中时,这也对我有用。没有办法在系统范围内改变这个,但由于递归可能效率低下,这可能是一件好事。您不能OPTION在内联表值函数的主体内指定查询提示(使用),如您的示例所示。

当您收到剧集并将输出存储在关系表中时,请考虑更改您的流程以仅遍历层次结构一次。您可以使用存储过程来执行此操作,因此不会遇到此限制。

我还认为您的代码中可能存在错误:如果您的 CTE 在 personId 上加入并在 eventId 上递归,那么我认为 eventId 101 会出现两次,作为重复。可能我误解了你的代码,让我知道你的想法。

HTH


car*_*son 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
Run Code Online (Sandbox Code Playgroud)

然后我像这样调用这个函数:

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
Run Code Online (Sandbox Code Playgroud)

这样,我的 CTE 逻辑就不需要重复,而且我也不需要在性能方面支付任何额外费用。必须这样做确实很麻烦,但我可以忍受。

  • 我不明白这如何解决递归问题。函数的调用不是递归的。 (3认同)
  • 我很清楚CTE是递归的。问题是**调用(函数调用)不是递归的**。例如,您可以使用“EventID=1”(以及 101,201、...901)来调用起始点(行)的函数。但原始查询(如果使用 MAXRECURSION=100000000 运行)可能永远不会访问“EventID=101”(以及 201、..、901)的行。因此,两个查询(原始查询和您的解决方案)可能会返回不同的结果(第一个查询中没有包含 101 的行,第二个查询中有包含 101 的行)!或者它可能会访问 101 但在步骤 100 之前,因此您的解决方案将在结果中包含该行两次(再次不同) (3认同)
  • 当然,除非数据通过连续的 EventID 值(1,2,,3...,99,100,101,..)连接。在这种情况下,您根本不需要递归 CTE。 (2认同)