Brent Ozar, Microsoft Certified Master, ha recentemente discusso del parallelismo in SQL Server, in particolare dei tipi di attesa CXPACKET e CXCONSUMER nella sua puntata finale della serie autunnale dei giorni di formazione del database di Quest. Nel suo solito modo umoristico e accessibile, Brent ha demistificato i concetti di parallelismo e ha spiegato come gestirlo quando vedi troppe statistiche di attesa di CXPACKET e CXCONSUMER.
Innanzitutto, cos'è il parallelismo e perché SQL Server esegue query in parallelo?
In poche parole, SQL Server riconosce automaticamente che una determinata query ha un carico di lavoro elevato e determina che il lavoro può essere svolto in modo più efficiente su più processori rispetto a uno solo. Questa è generalmente una decisione intelligente, ma può causare problemi quando SQL Server non bilancia il carico sui thread che eseguono l'attività.
Capire i tipi di attesa CXPACKET e CXCONSUMER
CXPACKET e CXCONSUMER sono tipi di attesa che indicano che il lavoro non è ugualmente bilanciato. Quando vedrai queste statistiche di attesa sul tuo server, saprai che SQL Server sta eseguendo query in parallelo, ma non sta facendo un ottimo lavoro nel distribuirle tra i processori disponibili.
Ogni professionista di database ha familiarità con il concetto di "costo" per esprimere quanto sia costosa l'esecuzione di una query in termini di consumo di risorse. Questi "query bucks" sono una misura approssimativa del lavoro e un segnale importante per stabilire se la query verrà eseguita in parallelo o meno. Una query economica non dovrà essere eseguita in parallelo, ma sarà necessaria una query costosa. L'obiettivo è eseguire la query nel modo più rapido ed efficiente possibile in modo che possa iniziare la successiva in linea. SQL Server designa un thread come utilità di pianificazione e questo thread, che Brent considerava il "robot overlord", assegnerà parti del carico di lavoro parallelo ai thread di lavoro o ai "robot minion".
Il parallelismo e il signore dei robot
Brent si è tuffato in una demo per mostrare come funziona. Utilizzando il database Stack Overflow, ha creato una ricerca nel database a basso costo che era molto veloce grazie alla presenza di un indice. Il piano di esecuzione era piuttosto semplice e non richiedeva il parallelismo per l'esecuzione.
Ma quando ha introdotto una ricerca per qualcosa che non era nell'indice, le cose sono cambiate forzando una ricerca di chiave per ogni riga nell'indice cluster della tabella. SQL Server ha riconosciuto che sarebbe stato molto lavoro, quindi ha introdotto il parallelismo e indicato come tale con un'icona sul piano di esecuzione. Se il piano di esecuzione fosse tridimensionale, saresti in grado di vedere i thread multipli impilati, ma poiché non lo è, devi visualizzare le statistiche per vedere informazioni come le letture logiche eseguite da ciascun thread della CPU.
Tuttavia, SQL Server ha assegnato questa attività solo a pochi thread, non a tutti. Brent ha spiegato che tutto ciò che accade oltre l'icona parallela sta accadendo solo sui processori assegnati. Quindi, i thread che hanno eseguito le letture iniziali sono ora gli unici a eseguire anche le ricerche delle chiavi. Il signore dei robot ha chiesto solo ad alcuni servitori di eseguire l'intero compito invece di chiedere a tutti i servitori di intervenire.
Ha continuato spiegando che SQL Server deve tenere conto di ciò che stanno facendo i thread e tenere traccia di ciò che sta facendo il robot overlord. All'inizio, tutto questo lavoro era rappresentato da una statistica di attesa, ma questo non aveva senso perché, in ogni caso, l'overlord deve ancora aspettare mentre tutti i thread funzionano. Quindi, è stato introdotto un nuovo tipo di attesa:questo era CXCONSUMER e tiene traccia di ciò che sta facendo il thread scheduler/overlord, mentre CXPACKET tiene traccia di ciò che stanno facendo i thread worker/minion.
Brent è tornato alla query per renderla ancora più complessa aggiungendo un ordinamento. Ora diventa ancora più chiaro che il parallelismo sta causando un problema piuttosto che rendere l'operazione più efficiente. Il lavoro è diventato ancora più sbilanciato tra i pochi thread di lavoro e alcuni stanno esaurendo la memoria e si riversano sul disco. Ha aggiunto un join, gravando ulteriormente sui nuclei lavorativi che non ricevono alcun aiuto dai non lavoratori. Le statistiche di CXPACKET hanno continuato a crescere.
Cosa puoi fare in questa situazione? La decisione sul parallelismo avviene a livello di server e non a livello di query, quindi saranno necessarie alcune modifiche alla configurazione.
Valutazione delle configurazioni chiave
Abbiamo già appreso che se il costo della query è superiore a un determinato livello, provoca la parallelizzazione di SQL Server. Le piccole query vengono vincolate a un singolo thread. Ma cosa controlla la soglia? È una proprietà chiamata Cost Threshold for Parallelism (CTFP). Per impostazione predefinita, se il piano di esecuzione determina che il costo è superiore a 5 dollari di query, la query verrà parallelizzata. Sebbene non ci siano indicazioni su come impostarlo, Brent consiglia un numero maggiore di 50. Questo eliminerà il parallelismo per le query banali.
Un'altra configurazione è il grado massimo di parallelismo (MAXDOP) che descrive il numero di thread che SQL Server assegnerà alla query. Il valore predefinito qui è zero, il che significa che SQL Server può utilizzare tutti i processori disponibili, fino a 64, per eseguire la query. L'impostazione dell'opzione MAXDOP su 1 limita SQL Server all'utilizzo di un solo processore, in effetti, costringendo un piano seriale a eseguire la query. SQL Server consiglierà un valore MAXDOP in base al numero di core del server che hai, ma in generale, un MAXDOP inferiore ha senso poiché non ci saranno molte volte in cui tutti i core saranno necessari.
Brent ha apportato modifiche a queste due configurazioni ed ha eseguito nuovamente la sua query. Questa volta, abbiamo potuto vedere che più core erano impegnati nell'operazione parallela. Le statistiche di attesa di CXPACKET erano inferiori, il che significava che il carico era bilanciato in modo più uniforme su più core rispetto a prima.
Suggerimenti per combattere le statistiche di attesa CXPACKET e CXCONSUMER
Brent consiglia i seguenti passaggi se visualizzi statistiche di attesa eccessive di CXPACKET e CXCONSUMER:
- Imposta CTFP e MAXDOP in base alle best practice del settore, quindi lascia che le impostazioni si attivino per alcuni giorni. Questo svuota la cache dei piani e obbliga SQL Server a ricostruire i piani di esecuzione delle query (rivalutare i costi).
- Apporta miglioramenti all'indice che riducano i tempi in cui le query vanno in parallelo per eseguire scansioni e ordinamenti. Lascia che i nuovi indici vengano preparati e poi cerca le query che stanno ancora facendo molto lavoro.
- Regola queste query e lasciale cuocere per alcuni giorni.
- Infine, se il parallelismo è ancora un problema serio, inizia a cercare le query specifiche con problemi di parallelismo.
Per ulteriori informazioni, puoi seguire l'intera sessione di formazione di Brent su CXPACKET e le statistiche di attesa su CXCONSUMER su richiesta di seguito.