How can I get rid of an unhelpful parallel branch when unpivoting a single row?NUMA Nodes - MAXDOP - PLESQL...

Examples of non trivial equivalence relations , I mean equivalence relations without the expression " same ... as" in their definition?

Why does nature favour the Laplacian?

How to reduce LED flash rate (frequency)

How could Tony Stark make this in Endgame?

What's the polite way to say "I need to urinate"?

How to verbalise code in Mathematica?

What software provides a code editing environment on iPad?

How can Republicans who favour free markets, consistently express anger when they don't like the outcome of that choice?

Will tsunami waves travel forever if there was no land?

The Defining Moment

What does the "ep" capability mean?

How much cash can I safely carry into the USA and avoid civil forfeiture?

A ​Note ​on ​N!

Mjolnir's timeline from Thor's perspective

Size of electromagnet needed to replicate Earth's magnetic field

a sore throat vs a strep throat vs strep throat

Do I have to worry about players making “bad” choices on level up?

Is there really no use for MD5 anymore?

Real-world applications of fields, rings and groups in linear algebra.

Map of water taps to fill bottles

Interpret a multiple linear regression when Y is log transformed

Is this homebrew Wind Wave spell balanced?

Do I have an "anti-research" personality?

Does Gita support doctrine of eternal cycle of birth and death for evil people?



How can I get rid of an unhelpful parallel branch when unpivoting a single row?


NUMA Nodes - MAXDOP - PLESQL Server thread statuswhy sql server has high Worker threads?Query memory grant and tempdb spillHow does PARALLEL_MIN_PERCENT affect parallel execution?SQL Server Threads and Degree Of ParallelismIs it possible to see which SPID uses which scheduler (worker thread)?SQL Server instance running out of worker threadsWhat's the easiest and most accurate way to visualize parallel thread usage in SQL Server?MAX worker thread in SQL server 2012/14/16






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}







10















Consider the following query that unpivots a few handfuls of scalar aggregates:



SELECT A, B
FROM (
SELECT
MAX(CASE WHEN ID = 1 THEN 1 ELSE 0 END) VAL1
, MAX(CASE WHEN ID = 2 THEN 1 ELSE 0 END) VAL2
, MAX(CASE WHEN ID = 3 THEN 1 ELSE 0 END) VAL3
, MAX(CASE WHEN ID = 4 THEN 1 ELSE 0 END) VAL4
, MAX(CASE WHEN ID = 5 THEN 1 ELSE 0 END) VAL5
, MAX(CASE WHEN ID = 6 THEN 1 ELSE 0 END) VAL6
, MAX(CASE WHEN ID = 7 THEN 1 ELSE 0 END) VAL7
, MAX(CASE WHEN ID = 16 THEN 1 ELSE 0 END) VAL16
FROM dbo.PARALLEL_ZONE_REPRO
) q
UNPIVOT(B FOR A IN (
VAL1
,VAL2
,VAL3
,VAL4
,VAL5
,VAL6
,VAL7
,VAL16
)) U
OPTION (MAXDOP 4);


On SQL Server 2017, I get a plan with two parallel branches. The left parallel branch feels out of place to me. The optimizer has a guarantee that there will be only a single row output from the global scalar aggregate, yet the parent operator of it is a Distribute Streams with round robin partitioning:



round robin



When I execute the query all of the rows go to a single thread as expected. There's no performance problem with this query, but the query reserves 8 parallel threads with MAXDOP set to 4. Again, I feel that this is out of place. It's impossible for both parallel branches to execute at the same time. I want to avoid unnecessary worker thread reservation because I have TF 2467 enabled which changes the scheduling algorithm to look at the number of worker threads per scheduler.



Is it possible to rewrite the query to have exactly one parallel branch that contains the table scan and local aggregate? For example, I would be fine with the general shape below except that I want the nested loop to execute in a serial zone:



enter image description here



For Application Reasons™ I strongly prefer to avoid splitting this query up into parts. If desired, you can view the actual query plan here. If you'd like to play along at home, here is T-SQL to create the table used in the query:



DROP TABLE IF EXISTS dbo.PARALLEL_ZONE_REPRO;

CREATE TABLE dbo.PARALLEL_ZONE_REPRO (
ID BIGINT,
FILLER VARCHAR(100)
);

INSERT INTO dbo.PARALLEL_ZONE_REPRO WITH (TABLOCK)
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) % 15
, REPLICATE('Z', 100)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;









share|improve this question

























  • Have you tried batch mode, or are there reasons that's not practical on the real-world example? For your toy example, if I introduce a dummy columnstore index into the original unpivot query (e.g., add WHERE NOT EXISTS (SELECT * FROM dbo.batchMode WHERE 0=1) with an empty dbo.batchMode table with columnstore index), the query plan reserved 5 threads and completes in about 1/3 the CPU time and elapsed time of the original query. The query does use a bit more memory though.

    – Geoff Patterson
    yesterday













  • @GeoffPatterson I can't get batch mode to stick with the real world example. If I get aggressive with a USE PLAN hint then I end up with really long compile times. On 2019 I do get batch mode plans without trying though. Details about the compile times: forrestmcdaniel.com/2018/07/31/use-plan-and-compile-time

    – Joe Obbish
    20 hours ago


















10















Consider the following query that unpivots a few handfuls of scalar aggregates:



SELECT A, B
FROM (
SELECT
MAX(CASE WHEN ID = 1 THEN 1 ELSE 0 END) VAL1
, MAX(CASE WHEN ID = 2 THEN 1 ELSE 0 END) VAL2
, MAX(CASE WHEN ID = 3 THEN 1 ELSE 0 END) VAL3
, MAX(CASE WHEN ID = 4 THEN 1 ELSE 0 END) VAL4
, MAX(CASE WHEN ID = 5 THEN 1 ELSE 0 END) VAL5
, MAX(CASE WHEN ID = 6 THEN 1 ELSE 0 END) VAL6
, MAX(CASE WHEN ID = 7 THEN 1 ELSE 0 END) VAL7
, MAX(CASE WHEN ID = 16 THEN 1 ELSE 0 END) VAL16
FROM dbo.PARALLEL_ZONE_REPRO
) q
UNPIVOT(B FOR A IN (
VAL1
,VAL2
,VAL3
,VAL4
,VAL5
,VAL6
,VAL7
,VAL16
)) U
OPTION (MAXDOP 4);


On SQL Server 2017, I get a plan with two parallel branches. The left parallel branch feels out of place to me. The optimizer has a guarantee that there will be only a single row output from the global scalar aggregate, yet the parent operator of it is a Distribute Streams with round robin partitioning:



round robin



When I execute the query all of the rows go to a single thread as expected. There's no performance problem with this query, but the query reserves 8 parallel threads with MAXDOP set to 4. Again, I feel that this is out of place. It's impossible for both parallel branches to execute at the same time. I want to avoid unnecessary worker thread reservation because I have TF 2467 enabled which changes the scheduling algorithm to look at the number of worker threads per scheduler.



Is it possible to rewrite the query to have exactly one parallel branch that contains the table scan and local aggregate? For example, I would be fine with the general shape below except that I want the nested loop to execute in a serial zone:



enter image description here



For Application Reasons™ I strongly prefer to avoid splitting this query up into parts. If desired, you can view the actual query plan here. If you'd like to play along at home, here is T-SQL to create the table used in the query:



DROP TABLE IF EXISTS dbo.PARALLEL_ZONE_REPRO;

CREATE TABLE dbo.PARALLEL_ZONE_REPRO (
ID BIGINT,
FILLER VARCHAR(100)
);

INSERT INTO dbo.PARALLEL_ZONE_REPRO WITH (TABLOCK)
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) % 15
, REPLICATE('Z', 100)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;









share|improve this question

























  • Have you tried batch mode, or are there reasons that's not practical on the real-world example? For your toy example, if I introduce a dummy columnstore index into the original unpivot query (e.g., add WHERE NOT EXISTS (SELECT * FROM dbo.batchMode WHERE 0=1) with an empty dbo.batchMode table with columnstore index), the query plan reserved 5 threads and completes in about 1/3 the CPU time and elapsed time of the original query. The query does use a bit more memory though.

    – Geoff Patterson
    yesterday













  • @GeoffPatterson I can't get batch mode to stick with the real world example. If I get aggressive with a USE PLAN hint then I end up with really long compile times. On 2019 I do get batch mode plans without trying though. Details about the compile times: forrestmcdaniel.com/2018/07/31/use-plan-and-compile-time

    – Joe Obbish
    20 hours ago














10












10








10


1






Consider the following query that unpivots a few handfuls of scalar aggregates:



SELECT A, B
FROM (
SELECT
MAX(CASE WHEN ID = 1 THEN 1 ELSE 0 END) VAL1
, MAX(CASE WHEN ID = 2 THEN 1 ELSE 0 END) VAL2
, MAX(CASE WHEN ID = 3 THEN 1 ELSE 0 END) VAL3
, MAX(CASE WHEN ID = 4 THEN 1 ELSE 0 END) VAL4
, MAX(CASE WHEN ID = 5 THEN 1 ELSE 0 END) VAL5
, MAX(CASE WHEN ID = 6 THEN 1 ELSE 0 END) VAL6
, MAX(CASE WHEN ID = 7 THEN 1 ELSE 0 END) VAL7
, MAX(CASE WHEN ID = 16 THEN 1 ELSE 0 END) VAL16
FROM dbo.PARALLEL_ZONE_REPRO
) q
UNPIVOT(B FOR A IN (
VAL1
,VAL2
,VAL3
,VAL4
,VAL5
,VAL6
,VAL7
,VAL16
)) U
OPTION (MAXDOP 4);


On SQL Server 2017, I get a plan with two parallel branches. The left parallel branch feels out of place to me. The optimizer has a guarantee that there will be only a single row output from the global scalar aggregate, yet the parent operator of it is a Distribute Streams with round robin partitioning:



round robin



When I execute the query all of the rows go to a single thread as expected. There's no performance problem with this query, but the query reserves 8 parallel threads with MAXDOP set to 4. Again, I feel that this is out of place. It's impossible for both parallel branches to execute at the same time. I want to avoid unnecessary worker thread reservation because I have TF 2467 enabled which changes the scheduling algorithm to look at the number of worker threads per scheduler.



Is it possible to rewrite the query to have exactly one parallel branch that contains the table scan and local aggregate? For example, I would be fine with the general shape below except that I want the nested loop to execute in a serial zone:



enter image description here



For Application Reasons™ I strongly prefer to avoid splitting this query up into parts. If desired, you can view the actual query plan here. If you'd like to play along at home, here is T-SQL to create the table used in the query:



DROP TABLE IF EXISTS dbo.PARALLEL_ZONE_REPRO;

CREATE TABLE dbo.PARALLEL_ZONE_REPRO (
ID BIGINT,
FILLER VARCHAR(100)
);

INSERT INTO dbo.PARALLEL_ZONE_REPRO WITH (TABLOCK)
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) % 15
, REPLICATE('Z', 100)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;









share|improve this question
















Consider the following query that unpivots a few handfuls of scalar aggregates:



SELECT A, B
FROM (
SELECT
MAX(CASE WHEN ID = 1 THEN 1 ELSE 0 END) VAL1
, MAX(CASE WHEN ID = 2 THEN 1 ELSE 0 END) VAL2
, MAX(CASE WHEN ID = 3 THEN 1 ELSE 0 END) VAL3
, MAX(CASE WHEN ID = 4 THEN 1 ELSE 0 END) VAL4
, MAX(CASE WHEN ID = 5 THEN 1 ELSE 0 END) VAL5
, MAX(CASE WHEN ID = 6 THEN 1 ELSE 0 END) VAL6
, MAX(CASE WHEN ID = 7 THEN 1 ELSE 0 END) VAL7
, MAX(CASE WHEN ID = 16 THEN 1 ELSE 0 END) VAL16
FROM dbo.PARALLEL_ZONE_REPRO
) q
UNPIVOT(B FOR A IN (
VAL1
,VAL2
,VAL3
,VAL4
,VAL5
,VAL6
,VAL7
,VAL16
)) U
OPTION (MAXDOP 4);


On SQL Server 2017, I get a plan with two parallel branches. The left parallel branch feels out of place to me. The optimizer has a guarantee that there will be only a single row output from the global scalar aggregate, yet the parent operator of it is a Distribute Streams with round robin partitioning:



round robin



When I execute the query all of the rows go to a single thread as expected. There's no performance problem with this query, but the query reserves 8 parallel threads with MAXDOP set to 4. Again, I feel that this is out of place. It's impossible for both parallel branches to execute at the same time. I want to avoid unnecessary worker thread reservation because I have TF 2467 enabled which changes the scheduling algorithm to look at the number of worker threads per scheduler.



Is it possible to rewrite the query to have exactly one parallel branch that contains the table scan and local aggregate? For example, I would be fine with the general shape below except that I want the nested loop to execute in a serial zone:



enter image description here



For Application Reasons™ I strongly prefer to avoid splitting this query up into parts. If desired, you can view the actual query plan here. If you'd like to play along at home, here is T-SQL to create the table used in the query:



DROP TABLE IF EXISTS dbo.PARALLEL_ZONE_REPRO;

CREATE TABLE dbo.PARALLEL_ZONE_REPRO (
ID BIGINT,
FILLER VARCHAR(100)
);

INSERT INTO dbo.PARALLEL_ZONE_REPRO WITH (TABLOCK)
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) % 15
, REPLICATE('Z', 100)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;






sql-server execution-plan sql-server-2017 parallelism






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited yesterday









Paul White

54.4k14288461




54.4k14288461










asked yesterday









Joe ObbishJoe Obbish

22.4k43494




22.4k43494













  • Have you tried batch mode, or are there reasons that's not practical on the real-world example? For your toy example, if I introduce a dummy columnstore index into the original unpivot query (e.g., add WHERE NOT EXISTS (SELECT * FROM dbo.batchMode WHERE 0=1) with an empty dbo.batchMode table with columnstore index), the query plan reserved 5 threads and completes in about 1/3 the CPU time and elapsed time of the original query. The query does use a bit more memory though.

    – Geoff Patterson
    yesterday













  • @GeoffPatterson I can't get batch mode to stick with the real world example. If I get aggressive with a USE PLAN hint then I end up with really long compile times. On 2019 I do get batch mode plans without trying though. Details about the compile times: forrestmcdaniel.com/2018/07/31/use-plan-and-compile-time

    – Joe Obbish
    20 hours ago



















  • Have you tried batch mode, or are there reasons that's not practical on the real-world example? For your toy example, if I introduce a dummy columnstore index into the original unpivot query (e.g., add WHERE NOT EXISTS (SELECT * FROM dbo.batchMode WHERE 0=1) with an empty dbo.batchMode table with columnstore index), the query plan reserved 5 threads and completes in about 1/3 the CPU time and elapsed time of the original query. The query does use a bit more memory though.

    – Geoff Patterson
    yesterday













  • @GeoffPatterson I can't get batch mode to stick with the real world example. If I get aggressive with a USE PLAN hint then I end up with really long compile times. On 2019 I do get batch mode plans without trying though. Details about the compile times: forrestmcdaniel.com/2018/07/31/use-plan-and-compile-time

    – Joe Obbish
    20 hours ago

















Have you tried batch mode, or are there reasons that's not practical on the real-world example? For your toy example, if I introduce a dummy columnstore index into the original unpivot query (e.g., add WHERE NOT EXISTS (SELECT * FROM dbo.batchMode WHERE 0=1) with an empty dbo.batchMode table with columnstore index), the query plan reserved 5 threads and completes in about 1/3 the CPU time and elapsed time of the original query. The query does use a bit more memory though.

– Geoff Patterson
yesterday







Have you tried batch mode, or are there reasons that's not practical on the real-world example? For your toy example, if I introduce a dummy columnstore index into the original unpivot query (e.g., add WHERE NOT EXISTS (SELECT * FROM dbo.batchMode WHERE 0=1) with an empty dbo.batchMode table with columnstore index), the query plan reserved 5 threads and completes in about 1/3 the CPU time and elapsed time of the original query. The query does use a bit more memory though.

– Geoff Patterson
yesterday















@GeoffPatterson I can't get batch mode to stick with the real world example. If I get aggressive with a USE PLAN hint then I end up with really long compile times. On 2019 I do get batch mode plans without trying though. Details about the compile times: forrestmcdaniel.com/2018/07/31/use-plan-and-compile-time

– Joe Obbish
20 hours ago





@GeoffPatterson I can't get batch mode to stick with the real world example. If I get aggressive with a USE PLAN hint then I end up with really long compile times. On 2019 I do get batch mode plans without trying though. Details about the compile times: forrestmcdaniel.com/2018/07/31/use-plan-and-compile-time

– Joe Obbish
20 hours ago










2 Answers
2






active

oldest

votes


















8














I am able to get the desired plan shape with a serial loop join when all of the following are true:




  • An APPLY or CROSS JOIN is used instead of UNPIVOT

  • The APPLY contains no outer references

  • The source of rows in the APPLY is a table value constructor as opposed to a table


For example, here is one way to do it:



SELECT A, B
FROM
(
SELECT A
, MAX(
CASE
WHEN A = 'VAL1' THEN VAL1
WHEN A = 'VAL2' THEN VAL2
WHEN A = 'VAL3' THEN VAL3
WHEN A = 'VAL4' THEN VAL4
WHEN A = 'VAL5' THEN VAL5
WHEN A = 'VAL6' THEN VAL6
WHEN A = 'VAL7' THEN VAL7
WHEN A = 'VAL16' THEN VAL16
ELSE NULL
END
) B
FROM (
SELECT
MAX(CASE WHEN ID = 1 THEN 1 ELSE 0 END) VAL1
, MAX(CASE WHEN ID = 2 THEN 1 ELSE 0 END) VAL2
, MAX(CASE WHEN ID = 3 THEN 1 ELSE 0 END) VAL3
, MAX(CASE WHEN ID = 4 THEN 1 ELSE 0 END) VAL4
, MAX(CASE WHEN ID = 5 THEN 1 ELSE 0 END) VAL5
, MAX(CASE WHEN ID = 6 THEN 1 ELSE 0 END) VAL6
, MAX(CASE WHEN ID = 7 THEN 1 ELSE 0 END) VAL7
, MAX(CASE WHEN ID = 16 THEN 1 ELSE 0 END) VAL16
FROM dbo.PARALLEL_ZONE_REPRO
) q
CROSS APPLY (
VALUES ('VAL1'), ('VAL2'), ('VAL3'), ('VAL4'),
('VAL5'), ('VAL6'), ('VAL7'), ('VAL16')
) ca (A)
GROUP BY A
) q
WHERE q.B IS NOT NULL
OPTION (MAXDOP 4);


I get the desired plan plan shape as claimed with just one parallel branch:



enter image description here



I tried many other things that did not work. This answer is unsatisfactory in that I don't know why it works and it may not work in a future version of SQL Server, but it did solve my problem.






share|improve this answer































    8















    It's impossible for both parallel branches to execute at the same time.




    Execution starts at the left edge of the plan. The nested loops branch is running (opening, waiting for data) when the table scan branch is running. This is unavoidable. Both branches are active at the same time, so SQL Server will reserve 2 * DOP workers for this plan.



    For a robust solution, you could place the pivot in a table-valued function:



    CREATE OR ALTER FUNCTION dbo.PivotPZR()
    RETURNS @R table
    (
    VAL1 bigint NOT NULL, VAL2 bigint NOT NULL,
    VAL3 bigint NOT NULL, VAL4 bigint NOT NULL,
    VAL5 bigint NOT NULL, VAL6 bigint NOT NULL,
    VAL7 bigint NOT NULL, VAL16 bigint NOT NULL
    )
    WITH SCHEMABINDING AS
    BEGIN
    DECLARE
    @Val1 bigint, @Val2 bigint, @Val3 bigint, @Val4 bigint,
    @Val5 bigint, @Val6 bigint, @Val7 bigint, @Val16 bigint;

    -- Can use parallelism
    SELECT
    @Val1 = MAX(CASE WHEN PZR.ID = 1 THEN 1 ELSE 0 END),
    @Val2 = MAX(CASE WHEN PZR.ID = 2 THEN 1 ELSE 0 END),
    @Val3 = MAX(CASE WHEN PZR.ID = 3 THEN 1 ELSE 0 END),
    @Val4 = MAX(CASE WHEN PZR.ID = 4 THEN 1 ELSE 0 END),
    @Val5 = MAX(CASE WHEN PZR.ID = 5 THEN 1 ELSE 0 END),
    @Val6 = MAX(CASE WHEN PZR.ID = 6 THEN 1 ELSE 0 END),
    @Val7 = MAX(CASE WHEN PZR.ID = 7 THEN 1 ELSE 0 END),
    @Val16 = MAX(CASE WHEN PZR.ID = 16 THEN 1 ELSE 0 END)
    FROM dbo.PARALLEL_ZONE_REPRO AS PZR;

    -- Single result row
    INSERT @R
    (VAL1, VAL2, VAL3, VAL4, VAL5, VAL6, VAL7, VAL16)
    VALUES
    (@Val1, @Val2, @Val3, @Val4, @Val5, @Val6, @Val7, @Val16);

    RETURN;
    END;


    Then rewrite the query as:



    SELECT
    U.A,
    U.B
    FROM dbo.PivotPZR() AS PP
    UNPIVOT
    (
    B FOR A IN (VAL1, VAL2 ,VAL3 ,VAL4, VAL5 ,VAL6 ,VAL7 ,VAL16)
    ) AS U;


    The function uses parallelism with a single branch as desired:



    Function plan



    The top-level execution plan is:



    Top-level query






    share|improve this answer


























      Your Answer








      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "182"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f236732%2fhow-can-i-get-rid-of-an-unhelpful-parallel-branch-when-unpivoting-a-single-row%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      8














      I am able to get the desired plan shape with a serial loop join when all of the following are true:




      • An APPLY or CROSS JOIN is used instead of UNPIVOT

      • The APPLY contains no outer references

      • The source of rows in the APPLY is a table value constructor as opposed to a table


      For example, here is one way to do it:



      SELECT A, B
      FROM
      (
      SELECT A
      , MAX(
      CASE
      WHEN A = 'VAL1' THEN VAL1
      WHEN A = 'VAL2' THEN VAL2
      WHEN A = 'VAL3' THEN VAL3
      WHEN A = 'VAL4' THEN VAL4
      WHEN A = 'VAL5' THEN VAL5
      WHEN A = 'VAL6' THEN VAL6
      WHEN A = 'VAL7' THEN VAL7
      WHEN A = 'VAL16' THEN VAL16
      ELSE NULL
      END
      ) B
      FROM (
      SELECT
      MAX(CASE WHEN ID = 1 THEN 1 ELSE 0 END) VAL1
      , MAX(CASE WHEN ID = 2 THEN 1 ELSE 0 END) VAL2
      , MAX(CASE WHEN ID = 3 THEN 1 ELSE 0 END) VAL3
      , MAX(CASE WHEN ID = 4 THEN 1 ELSE 0 END) VAL4
      , MAX(CASE WHEN ID = 5 THEN 1 ELSE 0 END) VAL5
      , MAX(CASE WHEN ID = 6 THEN 1 ELSE 0 END) VAL6
      , MAX(CASE WHEN ID = 7 THEN 1 ELSE 0 END) VAL7
      , MAX(CASE WHEN ID = 16 THEN 1 ELSE 0 END) VAL16
      FROM dbo.PARALLEL_ZONE_REPRO
      ) q
      CROSS APPLY (
      VALUES ('VAL1'), ('VAL2'), ('VAL3'), ('VAL4'),
      ('VAL5'), ('VAL6'), ('VAL7'), ('VAL16')
      ) ca (A)
      GROUP BY A
      ) q
      WHERE q.B IS NOT NULL
      OPTION (MAXDOP 4);


      I get the desired plan plan shape as claimed with just one parallel branch:



      enter image description here



      I tried many other things that did not work. This answer is unsatisfactory in that I don't know why it works and it may not work in a future version of SQL Server, but it did solve my problem.






      share|improve this answer




























        8














        I am able to get the desired plan shape with a serial loop join when all of the following are true:




        • An APPLY or CROSS JOIN is used instead of UNPIVOT

        • The APPLY contains no outer references

        • The source of rows in the APPLY is a table value constructor as opposed to a table


        For example, here is one way to do it:



        SELECT A, B
        FROM
        (
        SELECT A
        , MAX(
        CASE
        WHEN A = 'VAL1' THEN VAL1
        WHEN A = 'VAL2' THEN VAL2
        WHEN A = 'VAL3' THEN VAL3
        WHEN A = 'VAL4' THEN VAL4
        WHEN A = 'VAL5' THEN VAL5
        WHEN A = 'VAL6' THEN VAL6
        WHEN A = 'VAL7' THEN VAL7
        WHEN A = 'VAL16' THEN VAL16
        ELSE NULL
        END
        ) B
        FROM (
        SELECT
        MAX(CASE WHEN ID = 1 THEN 1 ELSE 0 END) VAL1
        , MAX(CASE WHEN ID = 2 THEN 1 ELSE 0 END) VAL2
        , MAX(CASE WHEN ID = 3 THEN 1 ELSE 0 END) VAL3
        , MAX(CASE WHEN ID = 4 THEN 1 ELSE 0 END) VAL4
        , MAX(CASE WHEN ID = 5 THEN 1 ELSE 0 END) VAL5
        , MAX(CASE WHEN ID = 6 THEN 1 ELSE 0 END) VAL6
        , MAX(CASE WHEN ID = 7 THEN 1 ELSE 0 END) VAL7
        , MAX(CASE WHEN ID = 16 THEN 1 ELSE 0 END) VAL16
        FROM dbo.PARALLEL_ZONE_REPRO
        ) q
        CROSS APPLY (
        VALUES ('VAL1'), ('VAL2'), ('VAL3'), ('VAL4'),
        ('VAL5'), ('VAL6'), ('VAL7'), ('VAL16')
        ) ca (A)
        GROUP BY A
        ) q
        WHERE q.B IS NOT NULL
        OPTION (MAXDOP 4);


        I get the desired plan plan shape as claimed with just one parallel branch:



        enter image description here



        I tried many other things that did not work. This answer is unsatisfactory in that I don't know why it works and it may not work in a future version of SQL Server, but it did solve my problem.






        share|improve this answer


























          8












          8








          8







          I am able to get the desired plan shape with a serial loop join when all of the following are true:




          • An APPLY or CROSS JOIN is used instead of UNPIVOT

          • The APPLY contains no outer references

          • The source of rows in the APPLY is a table value constructor as opposed to a table


          For example, here is one way to do it:



          SELECT A, B
          FROM
          (
          SELECT A
          , MAX(
          CASE
          WHEN A = 'VAL1' THEN VAL1
          WHEN A = 'VAL2' THEN VAL2
          WHEN A = 'VAL3' THEN VAL3
          WHEN A = 'VAL4' THEN VAL4
          WHEN A = 'VAL5' THEN VAL5
          WHEN A = 'VAL6' THEN VAL6
          WHEN A = 'VAL7' THEN VAL7
          WHEN A = 'VAL16' THEN VAL16
          ELSE NULL
          END
          ) B
          FROM (
          SELECT
          MAX(CASE WHEN ID = 1 THEN 1 ELSE 0 END) VAL1
          , MAX(CASE WHEN ID = 2 THEN 1 ELSE 0 END) VAL2
          , MAX(CASE WHEN ID = 3 THEN 1 ELSE 0 END) VAL3
          , MAX(CASE WHEN ID = 4 THEN 1 ELSE 0 END) VAL4
          , MAX(CASE WHEN ID = 5 THEN 1 ELSE 0 END) VAL5
          , MAX(CASE WHEN ID = 6 THEN 1 ELSE 0 END) VAL6
          , MAX(CASE WHEN ID = 7 THEN 1 ELSE 0 END) VAL7
          , MAX(CASE WHEN ID = 16 THEN 1 ELSE 0 END) VAL16
          FROM dbo.PARALLEL_ZONE_REPRO
          ) q
          CROSS APPLY (
          VALUES ('VAL1'), ('VAL2'), ('VAL3'), ('VAL4'),
          ('VAL5'), ('VAL6'), ('VAL7'), ('VAL16')
          ) ca (A)
          GROUP BY A
          ) q
          WHERE q.B IS NOT NULL
          OPTION (MAXDOP 4);


          I get the desired plan plan shape as claimed with just one parallel branch:



          enter image description here



          I tried many other things that did not work. This answer is unsatisfactory in that I don't know why it works and it may not work in a future version of SQL Server, but it did solve my problem.






          share|improve this answer













          I am able to get the desired plan shape with a serial loop join when all of the following are true:




          • An APPLY or CROSS JOIN is used instead of UNPIVOT

          • The APPLY contains no outer references

          • The source of rows in the APPLY is a table value constructor as opposed to a table


          For example, here is one way to do it:



          SELECT A, B
          FROM
          (
          SELECT A
          , MAX(
          CASE
          WHEN A = 'VAL1' THEN VAL1
          WHEN A = 'VAL2' THEN VAL2
          WHEN A = 'VAL3' THEN VAL3
          WHEN A = 'VAL4' THEN VAL4
          WHEN A = 'VAL5' THEN VAL5
          WHEN A = 'VAL6' THEN VAL6
          WHEN A = 'VAL7' THEN VAL7
          WHEN A = 'VAL16' THEN VAL16
          ELSE NULL
          END
          ) B
          FROM (
          SELECT
          MAX(CASE WHEN ID = 1 THEN 1 ELSE 0 END) VAL1
          , MAX(CASE WHEN ID = 2 THEN 1 ELSE 0 END) VAL2
          , MAX(CASE WHEN ID = 3 THEN 1 ELSE 0 END) VAL3
          , MAX(CASE WHEN ID = 4 THEN 1 ELSE 0 END) VAL4
          , MAX(CASE WHEN ID = 5 THEN 1 ELSE 0 END) VAL5
          , MAX(CASE WHEN ID = 6 THEN 1 ELSE 0 END) VAL6
          , MAX(CASE WHEN ID = 7 THEN 1 ELSE 0 END) VAL7
          , MAX(CASE WHEN ID = 16 THEN 1 ELSE 0 END) VAL16
          FROM dbo.PARALLEL_ZONE_REPRO
          ) q
          CROSS APPLY (
          VALUES ('VAL1'), ('VAL2'), ('VAL3'), ('VAL4'),
          ('VAL5'), ('VAL6'), ('VAL7'), ('VAL16')
          ) ca (A)
          GROUP BY A
          ) q
          WHERE q.B IS NOT NULL
          OPTION (MAXDOP 4);


          I get the desired plan plan shape as claimed with just one parallel branch:



          enter image description here



          I tried many other things that did not work. This answer is unsatisfactory in that I don't know why it works and it may not work in a future version of SQL Server, but it did solve my problem.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered yesterday









          Joe ObbishJoe Obbish

          22.4k43494




          22.4k43494

























              8















              It's impossible for both parallel branches to execute at the same time.




              Execution starts at the left edge of the plan. The nested loops branch is running (opening, waiting for data) when the table scan branch is running. This is unavoidable. Both branches are active at the same time, so SQL Server will reserve 2 * DOP workers for this plan.



              For a robust solution, you could place the pivot in a table-valued function:



              CREATE OR ALTER FUNCTION dbo.PivotPZR()
              RETURNS @R table
              (
              VAL1 bigint NOT NULL, VAL2 bigint NOT NULL,
              VAL3 bigint NOT NULL, VAL4 bigint NOT NULL,
              VAL5 bigint NOT NULL, VAL6 bigint NOT NULL,
              VAL7 bigint NOT NULL, VAL16 bigint NOT NULL
              )
              WITH SCHEMABINDING AS
              BEGIN
              DECLARE
              @Val1 bigint, @Val2 bigint, @Val3 bigint, @Val4 bigint,
              @Val5 bigint, @Val6 bigint, @Val7 bigint, @Val16 bigint;

              -- Can use parallelism
              SELECT
              @Val1 = MAX(CASE WHEN PZR.ID = 1 THEN 1 ELSE 0 END),
              @Val2 = MAX(CASE WHEN PZR.ID = 2 THEN 1 ELSE 0 END),
              @Val3 = MAX(CASE WHEN PZR.ID = 3 THEN 1 ELSE 0 END),
              @Val4 = MAX(CASE WHEN PZR.ID = 4 THEN 1 ELSE 0 END),
              @Val5 = MAX(CASE WHEN PZR.ID = 5 THEN 1 ELSE 0 END),
              @Val6 = MAX(CASE WHEN PZR.ID = 6 THEN 1 ELSE 0 END),
              @Val7 = MAX(CASE WHEN PZR.ID = 7 THEN 1 ELSE 0 END),
              @Val16 = MAX(CASE WHEN PZR.ID = 16 THEN 1 ELSE 0 END)
              FROM dbo.PARALLEL_ZONE_REPRO AS PZR;

              -- Single result row
              INSERT @R
              (VAL1, VAL2, VAL3, VAL4, VAL5, VAL6, VAL7, VAL16)
              VALUES
              (@Val1, @Val2, @Val3, @Val4, @Val5, @Val6, @Val7, @Val16);

              RETURN;
              END;


              Then rewrite the query as:



              SELECT
              U.A,
              U.B
              FROM dbo.PivotPZR() AS PP
              UNPIVOT
              (
              B FOR A IN (VAL1, VAL2 ,VAL3 ,VAL4, VAL5 ,VAL6 ,VAL7 ,VAL16)
              ) AS U;


              The function uses parallelism with a single branch as desired:



              Function plan



              The top-level execution plan is:



              Top-level query






              share|improve this answer






























                8















                It's impossible for both parallel branches to execute at the same time.




                Execution starts at the left edge of the plan. The nested loops branch is running (opening, waiting for data) when the table scan branch is running. This is unavoidable. Both branches are active at the same time, so SQL Server will reserve 2 * DOP workers for this plan.



                For a robust solution, you could place the pivot in a table-valued function:



                CREATE OR ALTER FUNCTION dbo.PivotPZR()
                RETURNS @R table
                (
                VAL1 bigint NOT NULL, VAL2 bigint NOT NULL,
                VAL3 bigint NOT NULL, VAL4 bigint NOT NULL,
                VAL5 bigint NOT NULL, VAL6 bigint NOT NULL,
                VAL7 bigint NOT NULL, VAL16 bigint NOT NULL
                )
                WITH SCHEMABINDING AS
                BEGIN
                DECLARE
                @Val1 bigint, @Val2 bigint, @Val3 bigint, @Val4 bigint,
                @Val5 bigint, @Val6 bigint, @Val7 bigint, @Val16 bigint;

                -- Can use parallelism
                SELECT
                @Val1 = MAX(CASE WHEN PZR.ID = 1 THEN 1 ELSE 0 END),
                @Val2 = MAX(CASE WHEN PZR.ID = 2 THEN 1 ELSE 0 END),
                @Val3 = MAX(CASE WHEN PZR.ID = 3 THEN 1 ELSE 0 END),
                @Val4 = MAX(CASE WHEN PZR.ID = 4 THEN 1 ELSE 0 END),
                @Val5 = MAX(CASE WHEN PZR.ID = 5 THEN 1 ELSE 0 END),
                @Val6 = MAX(CASE WHEN PZR.ID = 6 THEN 1 ELSE 0 END),
                @Val7 = MAX(CASE WHEN PZR.ID = 7 THEN 1 ELSE 0 END),
                @Val16 = MAX(CASE WHEN PZR.ID = 16 THEN 1 ELSE 0 END)
                FROM dbo.PARALLEL_ZONE_REPRO AS PZR;

                -- Single result row
                INSERT @R
                (VAL1, VAL2, VAL3, VAL4, VAL5, VAL6, VAL7, VAL16)
                VALUES
                (@Val1, @Val2, @Val3, @Val4, @Val5, @Val6, @Val7, @Val16);

                RETURN;
                END;


                Then rewrite the query as:



                SELECT
                U.A,
                U.B
                FROM dbo.PivotPZR() AS PP
                UNPIVOT
                (
                B FOR A IN (VAL1, VAL2 ,VAL3 ,VAL4, VAL5 ,VAL6 ,VAL7 ,VAL16)
                ) AS U;


                The function uses parallelism with a single branch as desired:



                Function plan



                The top-level execution plan is:



                Top-level query






                share|improve this answer




























                  8












                  8








                  8








                  It's impossible for both parallel branches to execute at the same time.




                  Execution starts at the left edge of the plan. The nested loops branch is running (opening, waiting for data) when the table scan branch is running. This is unavoidable. Both branches are active at the same time, so SQL Server will reserve 2 * DOP workers for this plan.



                  For a robust solution, you could place the pivot in a table-valued function:



                  CREATE OR ALTER FUNCTION dbo.PivotPZR()
                  RETURNS @R table
                  (
                  VAL1 bigint NOT NULL, VAL2 bigint NOT NULL,
                  VAL3 bigint NOT NULL, VAL4 bigint NOT NULL,
                  VAL5 bigint NOT NULL, VAL6 bigint NOT NULL,
                  VAL7 bigint NOT NULL, VAL16 bigint NOT NULL
                  )
                  WITH SCHEMABINDING AS
                  BEGIN
                  DECLARE
                  @Val1 bigint, @Val2 bigint, @Val3 bigint, @Val4 bigint,
                  @Val5 bigint, @Val6 bigint, @Val7 bigint, @Val16 bigint;

                  -- Can use parallelism
                  SELECT
                  @Val1 = MAX(CASE WHEN PZR.ID = 1 THEN 1 ELSE 0 END),
                  @Val2 = MAX(CASE WHEN PZR.ID = 2 THEN 1 ELSE 0 END),
                  @Val3 = MAX(CASE WHEN PZR.ID = 3 THEN 1 ELSE 0 END),
                  @Val4 = MAX(CASE WHEN PZR.ID = 4 THEN 1 ELSE 0 END),
                  @Val5 = MAX(CASE WHEN PZR.ID = 5 THEN 1 ELSE 0 END),
                  @Val6 = MAX(CASE WHEN PZR.ID = 6 THEN 1 ELSE 0 END),
                  @Val7 = MAX(CASE WHEN PZR.ID = 7 THEN 1 ELSE 0 END),
                  @Val16 = MAX(CASE WHEN PZR.ID = 16 THEN 1 ELSE 0 END)
                  FROM dbo.PARALLEL_ZONE_REPRO AS PZR;

                  -- Single result row
                  INSERT @R
                  (VAL1, VAL2, VAL3, VAL4, VAL5, VAL6, VAL7, VAL16)
                  VALUES
                  (@Val1, @Val2, @Val3, @Val4, @Val5, @Val6, @Val7, @Val16);

                  RETURN;
                  END;


                  Then rewrite the query as:



                  SELECT
                  U.A,
                  U.B
                  FROM dbo.PivotPZR() AS PP
                  UNPIVOT
                  (
                  B FOR A IN (VAL1, VAL2 ,VAL3 ,VAL4, VAL5 ,VAL6 ,VAL7 ,VAL16)
                  ) AS U;


                  The function uses parallelism with a single branch as desired:



                  Function plan



                  The top-level execution plan is:



                  Top-level query






                  share|improve this answer
















                  It's impossible for both parallel branches to execute at the same time.




                  Execution starts at the left edge of the plan. The nested loops branch is running (opening, waiting for data) when the table scan branch is running. This is unavoidable. Both branches are active at the same time, so SQL Server will reserve 2 * DOP workers for this plan.



                  For a robust solution, you could place the pivot in a table-valued function:



                  CREATE OR ALTER FUNCTION dbo.PivotPZR()
                  RETURNS @R table
                  (
                  VAL1 bigint NOT NULL, VAL2 bigint NOT NULL,
                  VAL3 bigint NOT NULL, VAL4 bigint NOT NULL,
                  VAL5 bigint NOT NULL, VAL6 bigint NOT NULL,
                  VAL7 bigint NOT NULL, VAL16 bigint NOT NULL
                  )
                  WITH SCHEMABINDING AS
                  BEGIN
                  DECLARE
                  @Val1 bigint, @Val2 bigint, @Val3 bigint, @Val4 bigint,
                  @Val5 bigint, @Val6 bigint, @Val7 bigint, @Val16 bigint;

                  -- Can use parallelism
                  SELECT
                  @Val1 = MAX(CASE WHEN PZR.ID = 1 THEN 1 ELSE 0 END),
                  @Val2 = MAX(CASE WHEN PZR.ID = 2 THEN 1 ELSE 0 END),
                  @Val3 = MAX(CASE WHEN PZR.ID = 3 THEN 1 ELSE 0 END),
                  @Val4 = MAX(CASE WHEN PZR.ID = 4 THEN 1 ELSE 0 END),
                  @Val5 = MAX(CASE WHEN PZR.ID = 5 THEN 1 ELSE 0 END),
                  @Val6 = MAX(CASE WHEN PZR.ID = 6 THEN 1 ELSE 0 END),
                  @Val7 = MAX(CASE WHEN PZR.ID = 7 THEN 1 ELSE 0 END),
                  @Val16 = MAX(CASE WHEN PZR.ID = 16 THEN 1 ELSE 0 END)
                  FROM dbo.PARALLEL_ZONE_REPRO AS PZR;

                  -- Single result row
                  INSERT @R
                  (VAL1, VAL2, VAL3, VAL4, VAL5, VAL6, VAL7, VAL16)
                  VALUES
                  (@Val1, @Val2, @Val3, @Val4, @Val5, @Val6, @Val7, @Val16);

                  RETURN;
                  END;


                  Then rewrite the query as:



                  SELECT
                  U.A,
                  U.B
                  FROM dbo.PivotPZR() AS PP
                  UNPIVOT
                  (
                  B FOR A IN (VAL1, VAL2 ,VAL3 ,VAL4, VAL5 ,VAL6 ,VAL7 ,VAL16)
                  ) AS U;


                  The function uses parallelism with a single branch as desired:



                  Function plan



                  The top-level execution plan is:



                  Top-level query







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited yesterday

























                  answered yesterday









                  Paul WhitePaul White

                  54.4k14288461




                  54.4k14288461






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Database Administrators Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f236732%2fhow-can-i-get-rid-of-an-unhelpful-parallel-branch-when-unpivoting-a-single-row%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Cannot install PyQt5 The Next CEO of Stack OverflowCannot install tcpreplay 3.4.4cannot...

                      Kapp-Putsch Acontecimentos | Outros artigos | Menu de navegação

                      Why did early computer designers eschew integers? The Next CEO of Stack OverflowWhat register...