Perché l'operatore Parallelism (Repartition Streams) dovrebbe ridurre le stime delle righe a 1?


12

Sto usando SQL Server 2012 Enterprise. Mi sono imbattuto in un piano SQL che mostra alcuni comportamenti che non trovo del tutto intuitivi. Dopo un'operazione di Scansione indice parallela pesante, si verifica un'operazione di parallelismo (stream di ripartizione), ma sta uccidendo le stime di riga restituite dalla scansione indice (Object10.Index2), riducendo la stima a 1. Ho effettuato alcune ricerche, ma non ho trovato nulla che spieghi questo comportamento. La query è abbastanza semplice, sebbene ciascuna delle tabelle contenga record in milioni bassi. Questo fa parte di un processo di caricamento DWH e questo set di dati intermedi viene toccato alcune volte in tutto, ma la domanda che ho è relativa in particolare alle stime delle righe. Qualcuno può spiegare perché le stime accurate delle righe vanno a 1 all'interno dell'operatore Parallelism (Repartition Strems)? Anche,

Ho pubblicato il piano completo per Incolla il piano .

Ecco l'operazione in questione:

inserisci qui la descrizione dell'immagine

Incluso l'albero del piano nel caso in cui si aggiunga altro contesto:

inserisci qui la descrizione dell'immagine

Potrei imbattermi in qualche variante di questo articolo Connect archiviato da Paul White (ulteriori approfondimenti sul suo blog qui )? Almeno è l'unica cosa che ho trovato che sembra essere anche lontanamente vicino a quello in cui mi imbatto, anche se non c'è nessun operatore TOP in gioco.

Risposte:


9

I piani di query con filtri bitmap possono talvolta essere difficili da leggere. Da l'articolo BOL per i flussi partiziona (sottolineatura mia):

L'operatore Repartition Streams consuma più flussi e produce più flussi di record. Il contenuto e il formato del record non vengono modificati. Se Query Optimizer utilizza un filtro bitmap, il numero di righe nel flusso di output viene ridotto.

Inoltre, è utile anche un articolo sui filtri bitmap:

Quando si analizza un piano di esecuzione contenente il filtro bitmap, è importante capire come i dati scorrono attraverso il piano e dove viene applicato il filtro. Il filtro bitmap e la bitmap ottimizzata vengono creati sul lato input di compilazione (tabella delle dimensioni) di un join hash; tuttavia, il filtraggio effettivo viene in genere eseguito all'interno dell'operatore Parallelism, che si trova sul lato di input della sonda (la tabella dei fatti) del join hash. Tuttavia, quando il filtro bitmap si basa su una colonna intera, il filtro può essere applicato direttamente alla tabella iniziale o all'operazione di scansione dell'indice anziché all'operatore Parallelismo. Questa tecnica si chiama ottimizzazione nella riga.

Credo sia quello che stai osservando con la tua domanda. È possibile elaborare una demo relativamente semplice per mostrare un operatore di flussi di ripartizione che riduce una stima di cardinalità, anche quando l'operatore bitmap è in IN_ROWcontrasto con la tabella dei fatti. Preparazione dati:

create table outer_tbl (ID BIGINT NOT NULL);

INSERT INTO outer_tbl WITH (TABLOCK)
SELECT TOP (1000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values;

create table inner_tbl_1 (ID BIGINT NULL);
create table inner_tbl_2 (ID BIGINT NULL);

INSERT INTO inner_tbl_1 WITH (TABLOCK)
SELECT (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) / 2000000 - 2) NUM
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

INSERT INTO inner_tbl_2 WITH (TABLOCK)
SELECT (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) / 2000000 - 2) NUM
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

Ecco una query che non dovresti eseguire:

SELECT *
FROM outer_tbl o
INNER JOIN inner_tbl_1 i ON o.ID = i.ID
INNER JOIN inner_tbl_2 i2 ON o.ID = i2.ID
OPTION (HASH JOIN, QUERYTRACEON 9481, QUERYTRACEON 8649);

Ho caricato il piano . Dai un'occhiata all'operatore vicino inner_tbl_2:

ripartizione delle righe perdenti

Puoi anche trovare utile il secondo test in Hash Joins on Nullable Columns di Paul White.

Ci sono alcune incongruenze nel modo in cui viene applicata la riduzione delle righe. Sono stato in grado di vederlo solo in un piano con almeno tre tavoli. Tuttavia, la riduzione delle righe previste sembra ragionevole con la giusta distribuzione dei dati. Supponiamo che la colonna unita nella tabella dei fatti abbia molti valori ripetuti che non sono presenti nella tabella delle dimensioni. Un filtro bitmap potrebbe eliminare quelle righe prima che raggiungano il join. Per la tua query la stima è ridotta completamente a 1. Il modo in cui le righe sono distribuite nella funzione hash fornisce un buon suggerimento:

riga distro

Sulla base di ciò, ho il sospetto che tu abbia molti valori ripetuti per la Object1.Column21colonna. Se le colonne ripetute non si trovano nell'istogramma delle statistiche per Object4.Column19allora SQL Server potrebbe sbagliare la stima della cardinalità.

Penso che dovresti preoccuparti del fatto che potrebbe essere possibile migliorare le prestazioni della query. Naturalmente, se la query soddisfa i tempi di risposta o i requisiti SLA, potrebbe non valere la pena indagare ulteriormente. Tuttavia, se desideri indagare ulteriormente, ci sono alcune cose che puoi fare (oltre all'aggiornamento delle statistiche) per farti un'idea se lo Strumento per ottimizzare le query sceglierebbe un piano migliore se avesse informazioni migliori. È possibile inserire i risultati del join tra Database1.Schema1.Object10e Database1.Schema1.Object11in una tabella temporanea e vedere se si continuano a ottenere join loop nidificati. È possibile modificare tale join in a in LEFT OUTER JOINmodo che Query Optimizer non riduca il numero di righe in quel passaggio. È possibile aggiungere un MAXDOP 1suggerimento alla query per vedere cosa succede. Puoi usareTOPinsieme a una tabella derivata per forzare l'ultimo join, oppure è possibile anche commentare il join dalla query. Spero che questi suggerimenti siano sufficienti per iniziare.

Per quanto riguarda l' elemento di connessione nella domanda, è estremamente improbabile che sia correlato alla tua domanda. Tale problema non ha a che fare con stime di righe scadenti. Ha a che fare con una condizione di competizione in parallelismo che causa l'elaborazione di troppe righe nel piano di query dietro le quinte. Qui sembra che la tua query non stia facendo alcun lavoro extra.


6

Il problema principale qui è una scarsa stima della cardinalità per il risultato del primo join. Ciò potrebbe sorgere per molte ragioni, ma molto spesso si tratta di statistiche obsolete o di un numero di predicati di join correlati, che il modello predefinito dell'ottimizzatore presuppone siano indipendenti.

In quest'ultimo caso, FIX: prestazioni scadenti quando si esegue una query che contiene predicati AND correlati in SQL Server 2008 o in SQL Server 2008 R2 o in SQL Server 2012 può essere pertinente utilizzando il flag di traccia 4137 supportato. È inoltre possibile provare la query con trace flag 4199 per abilitare le correzioni dell'ottimizzatore e / o 2301 per abilitare le estensioni di modellazione. È difficile da sapere sulla base di un piano anonimo.

La presenza della bitmap non influisce direttamente sulla stima della cardinalità del join, ma rende il suo effetto visibile prima applicando la riduzione iniziale del semijoin. Senza la bitmap, la stima della cardinalità per il primo join sarebbe la stessa e il resto del piano sarebbe comunque ottimizzato di conseguenza.

Se sei curioso, su un sistema di test, puoi disabilitare le bitmap per la query con flag di traccia 7498. Puoi anche disabilitare le bitmap ottimizzate (considerate dall'ottimizzatore e influire sulle stime di cardinalità), sostituendole con bitmap post-ottimizzazione (non considerate dall'ottimizzatore, nessun effetto sulla cardinalità) con una combinazione di flag di traccia 7497 e 7498. Nessuno dei due è documentato o supportato per l'uso su un sistema di produzione, ma producono piani che l'ottimizzatore potrebbe considerare normalmente, e quindi può essere forzato con un guida al piano.

Niente di tutto ciò risolverà il problema principale della stima scadente per il primo join, come indicato sopra, quindi lo sto solo citando per motivi di interesse.

Ulteriori letture su bitmap e hash join:


0

ti ha risposto su Twitter. Ho guardato l'XML allegato e ho visto un parallelismo sbilanciato. 1 thread ha quasi tutte le righe effettive mentre la maggior parte delle altre no. Sta urlando un parallelismo sbilanciato. Pertanto, esaminerei il valore chiave / join e le rispettive statistiche e cardinalità.

Per tua altra idea, non sono così sicuro che l'articolo Connect si applichi, dal momento che il tuo piano incollato non contiene TOP ovunque abbia visto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.