Quantcast
Viewing all articles
Browse latest Browse all 207

How does SQL Server know not to execute Anchor element in Recursion CTE for 2nd Iteration / 1st Recursion?

I've been reading up on the inner workings of CTE Recursion and I'm still not quite sure how SQL Server is implementing the Anchor element in their source code and how SQL Server Query Execution Engine / Query Optimizer is then interpreting those instruction sets.

I read through the following article very carefully to follow the logic:http://sqlchitchat.com/sqldev/tsql/recursive-cte/

Let's take Example 1 from said article:https://github.com/dmincic/SQLCHITCHAT/blob/master/CTE/Sql/Example1_cteQuery.sql

DECLARE @EmpId INT = 3;;WITH cte1 AS(    -- Anchor Element    SELECT EmpId          ,MgrId    FROM dbo.Employees    WHERE MgrId = @EmpId    UNION ALL    -- Recursive Element    SELECT e.EmpId          ,e.MgrId    FROM dbo.Employees e      INNER JOIN cte1 c        ON e.MgrId = c.EmpId)-- Invoke CTE RecursionSELECT cte1.EmpId      ,cte1.MgrIdFROM cte1;

If you scroll down to about the middle of the article, it talks about the role of the anchor element in the 2nd iteration / 1st recursion:

The second iteration begins.This is the first recursion. The anchor part played its part in the first iteration and from now on returns only empty sets. However, the recursive part can now reference it’s previous result(cte1 value after the first iteration) in the INNER JOIN operator. The table operation produces the result of the second iteration as shown in the figure below.

Figure 5: https://sqlchitchat.com/wp-content/uploads/2019/10/2nd_Iteration1.png

Image may be NSFW.
Clik here to view.
FIgure 5, cte1 value after 2nd iteration

In the Figure, you can see the empty set (well, tuple) drawn out for EmpId and MgrId.

Then I read through How does SQL recursion actually work? and it appears, from the answers provided, the Anchor Element is not even evaluated for N+1 iterations.

So, which one is it then? Is the QE/QO evaluating the Anchor on every iteration and, somehow, it returns an empty tuple during recursion or is the Anchor being skipped outright during recursion and, thus, it would never return an empty tuple?

To clarify my question, here's what I'm asking: Does the underlying code resemble this:

static void Main(string[] args){    int Number = 0;    long Result;    // Anchor part    Number = GetNumberFromProgramArguments();    // Anchor part is only executed once    // Recursive part    Result = CalculateFactorial(Number);}public static long CalculateFactorial(int number){    // Termination check    if (number == 0)        return 1;    // Recursive call    return number * CalculateFactorial(number - 1);}

Or is it more like this:

static void Main(string[] args){    int Number = 0;    long Result;    int RecursionLevel = 0;    // Recursive part    Result = CalculateFactorial(Number, RecursionLevel);}public static long CalculateFactorial(int number, int recursionLevel){   // Run Anchor part only if Recursion Level is 0   if (recursionLevel == 0)       // Anchor part       number = GetNumberFromProgramArguments();   // Termination check   if (number == 0)       return 1;    // Increment recursion    recursionLevel++;    // Recursive call    return number * CalculateFactorial(number - 1, recursionLevel);}

It's not the greatest example because I've been focusing on tables, not numbers, but I hope you get my point. Why is the article stating that the Anchor is being evaluated and returned as an empty tuple during recursion? That's where I'm getting confused here. It doesn't make sense. The SQL Execution plan doesn't show the Anchor part being evaluated for N+1 iterations, just the very first iteration. And if that's the case, then the anchor part would never return anything during recursion because execution never reaches that part of the code again to even evaluate the anchor. I don't understand why Figure 5 is showing anchor being evaluated as an empty tuple during recursion. It shouldn't even show anything.

Yes, I understand that recursion is grabbing the previous iteration, if it's available. But from Figure 5 and from the paragraph I quoted, the blog is stating that the anchor executes every iteration and returns an empty tuple for the recursion part, which is not evident from the SQL Execution Plan. The Execution Plan shows the Anchor executing once and never again. Do you see why I'm getting confused here?


Viewing all articles
Browse latest Browse all 207

Trending Articles