Tek bir satırı açarken yararsız bir paralel daldan nasıl kurtulabilirim?


9

Birkaç avuç skaler agregayı açan aşağıdaki sorguyu düşünün:

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

SQL Server 2017'de, iki paralel dalı olan bir plan alıyorum. Sol paralel dal bana yerinde hissetmiyor. Optimize edici, global skaler agregattan yalnızca tek bir satır çıkışı olacağının garantisine sahiptir, ancak bunun ana operatörü, yuvarlak robin bölümlemeli bir Dağıtma Akışıdır:

yuvarlak robin

Sorguyu yürüttüğümde tüm satırlar beklendiği gibi tek bir iş parçacığına gider. Bu sorgu ile herhangi bir performans sorunu yok, ancak sorgu 4 olarak ayarlanmış MAXDOP ile 8 paralel iş parçacıkları ayırır. Yine, bunun yerinde olduğunu hissediyorum. Her iki paralel dalın aynı anda yürütülmesi imkansızdır. TF 2467 zamanlayıcı algoritması başına zamanlayıcı iş parçacığı sayısına bakmak için değiştiren TF 2467 etkin olduğundan gereksiz işçi iş parçacığı rezervasyon önlemek istiyorum.

Sorgu, tablo taraması ve yerel toplamı içeren tam olarak bir paralel dal olacak şekilde yeniden yazılabilir mi? Örneğin, iç içe döngü bir seri bölgede yürütmek istiyorum dışında genel şekli ile iyi olurdu:

resim açıklamasını buraya girin

Application Reasons ™ için bu sorguyu parçalara ayırmaktan kesinlikle kaçınmayı tercih ederim. İsterseniz, gerçek sorgu planını burada görüntüleyebilirsiniz . Evde oynamak istiyorsanız, sorguda kullanılan tabloyu oluşturmak için T-SQL:

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;

Yanıtlar:


8

Aşağıdakilerin hepsi doğru olduğunda bir seri döngü birleştirme ile istenen plan şekli elde edebiliyoruz:

  • Yerine bir APPLYveya CROSS JOINkullanılırUNPIVOT
  • APPLYBir dış referanslar içerir
  • İçindeki satırların kaynağı APPLYbir tablonun aksine bir tablo değeri yapıcısıdır

Örneğin, bunu yapmanın bir yolu:

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

Sadece bir paralel dal ile talep edildiği gibi plan planı şeklini alıyorum:

resim açıklamasını buraya girin

İşe yaramayan birçok şeyi denedim. Bu cevap, neden çalıştığını bilmediğim için tatmin edici değil ve SQL Server'ın gelecekteki bir sürümünde çalışmayabilir, ancak sorunumu çözdü.


8

Her iki paralel dalın aynı anda yürütülmesi imkansızdır.

Uygulama , planın sol kenarında başlar . Tablo tarama dalı çalışırken iç içe döngüler dalı çalışıyor (açılıyor, veri bekleniyor). Bu kaçınılmaz . SQL Server böylece ikisi de dalları, aynı anda etkin olan rezerv bu plan için 2 * DOP işçileri.

Sağlam bir çözüm için, pivotu tablo değerli bir işleve yerleştirebilirsiniz:

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;

Ardından sorguyu şu şekilde yeniden yazın:

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;

İşlev istendiği gibi tek bir dal ile paralellik kullanır:

İşlev planı

Üst düzey yürütme planı:

Üst düzey sorgu

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.