Il supporto per Parallel Scalar UDF è una richiesta di funzionalità ragionevole?


10

È abbastanza ben documentato che l'UDF scalare forza un piano seriale globale.

Esecuzione di funzioni in parallelo

Dato un gran numero di righe che entrano in un punto della pipeline in cui deve essere calcolato un UDF, perché il motore non può semplicemente distribuirle tra i processori? Se non esiste uno stato all'interno di un UDF, l'ordine non dovrebbe avere importanza.

Ci sono affermazioni sul fatto che UDF sia una scatola nera che deve usare il cursore. Vedo che un cursore utente non può essere parallelizzato all'interno di un SP per i casi in cui un certo stato viene mantenuto tra le iterazioni ma sembra che dovrebbe essere parallelizzabile altrimenti.

Punti extra per spiegare perché il motore costringe l'intero piano ad essere seriale invece della sola fase di calcolo UDF.

Il supporto per UDF parallelo è una funzione ragionevole da richiedere?


1
La reazione appropriata sembra essere, come notato nella risposta accettata al tuo link, per riscrivere qualsiasi funzione scalare definita dall'utente come funzioni con valori di tabella incorporata a colonna singola . Questi sono espansi allo stesso modo di una vista e sono quindi completamente ottimizzati. In questa luce, la tua domanda ha ancora valore?
Pieter Geerkens,

1
Sì in caso di successo con la soluzione alternativa TVF. Ho chiesto perché sembra sbagliato evitare di usare un costrutto così naturale. Inoltre, non è pratico aspettarsi che i nuovi sviluppatori SQL imparino gli interni UDF.
crokusek,

Commento chiarificatore. Successo con ITVF ma non TVF multi-dichiarazione.
crokusek,

Risposte:


17

È abbastanza ben documentato che gli UDF impongono un piano seriale globale.

Non sono sicuro che sia tutto ben documentato.

  • Una funzione scalare T-SQL impedisce il parallelismo in qualsiasi punto del piano.
  • Una funzione CLR scalare può essere eseguita in parallelo, purché non acceda al database.
  • Una funzione T-SQL con valori di tabella multi-istruzione forza una zona seriale in un piano che può usare il parallelismo altrove.
  • Una funzione T-SQL con valori di tabella incorporata viene espansa come una vista, quindi non ha alcun effetto diretto.

Vedi Forcing a Parallel Execution Plan e / o presentazione di Craig Freedman's Parallel Execution .

Ci sono affermazioni sul fatto che UDFs sia una scatola nera che deve usare il cursore.

Queste affermazioni non sono corrette.

Punti extra per spiegare perché il motore costringe l'intero piano ad essere seriale invece della sola fase di calcolo UDF.

La mia comprensione è che le attuali restrizioni sono semplicemente il risultato di alcuni dettagli di implementazione. Non vi è alcun motivo fondamentale per cui le funzioni non possano essere eseguite utilizzando il parallelismo.

In particolare, le funzioni scalari T-SQL vengono eseguite all'interno di un contesto T-SQL separato, il che complica in modo significativo il corretto funzionamento, il coordinamento e l'arresto (soprattutto in caso di errore).

Allo stesso modo, le variabili di tabella supportano le letture parallele (ma non le scritture) in generale, ma la variabile di tabella esposta da una funzione con valori di tabella non è in grado di supportare letture parallele per motivi specifici dell'implementazione. Avresti bisogno di qualcuno con accesso al codice sorgente (e la libertà di condividere i dettagli) per fornire una risposta autorevole, temo.

Il supporto per UDF parallelo è una funzione ragionevole da richiedere?

Certo, se riesci a fare un caso abbastanza forte. La mia sensazione è che il lavoro in questione sarebbe esteso, quindi la tua proposta dovrebbe raggiungere un livello estremamente alto. Ad esempio, un correlato (e molto più semplice) richiesta per fornire funzioni inline scalari ha grande sostegno, ma ha languito non implementato ormai da anni.


Ti potrebbe piacere leggere l'articolo di Microsoft:

... che delinea l'approccio che Microsoft intende adottare per risolvere i problemi di prestazioni della funzione scalare T-SQL nella versione successiva a SQL Server 2017.

L'obiettivo di Froid è consentire agli sviluppatori di utilizzare le astrazioni di UDF e procedure senza compromettere le prestazioni. Froid raggiunge questo obiettivo usando una nuova tecnica per convertire automaticamente i programmi imperativi in ​​equivalenti forme algebriche relazionali ogni volta che è possibile. Froid modella i blocchi di codice imperativo come espressioni relazionali e li combina sistematicamente in un'unica espressione utilizzando l'operatore Applica, consentendo così all'ottimizzatore di query di scegliere piani di query paralleli orientati al set efficienti .

(enfatizzare il mio)


Le funzioni T-SQL scalari incorporate sono ora implementate in SQL Server 2019 .


11

Come Paolo ha giustamente menzionato nella sua risposta, non vi è alcun motivo fondamentale per cui le UDF scalari non possano essere eseguite usando il parallelismo. Tuttavia, a parte le sfide legate all'implementazione, c'è un'altra ragione per costringerle a essere seriali. L' articolo di Froid citato da Paul fornisce ulteriori informazioni al riguardo.

Citando dal documento (Sezione 2.3):

Attualmente, SQL Server non utilizza il parallelismo intra-query nelle query che invocano UDF. I metodi possono essere progettati per mitigare questa limitazione, ma introducono ulteriori sfide, come la scelta del giusto grado di parallelismo per ogni invocazione dell'UDF.

Ad esempio, si consideri un UDF che richiama altre query SQL, come quella nella Figura 1. Ciascuna di tali query può a sua volta utilizzare il parallelismo e, pertanto, l'ottimizzatore non ha modo di sapere come condividere i thread attraverso di essi, a meno che non guardi nel UDF e decide il grado di parallelismo per ciascuna query all'interno (che potrebbe potenzialmente cambiare da una chiamata a un'altra). Con gli UDF nidificati e ricorsivi, questo problema diventa ancora più difficile da gestire.

L'approccio di Froid, come descritto nel documento, non solo si tradurrà in piani paralleli, ma aggiunge anche molti più vantaggi per le query con UDF. In sostanza, sottrae la tua richiesta di esecuzione parallela di UDF.

Aggiornamento: Froid è ora disponibile come funzionalità dell'anteprima di SQL Server 2019. La funzione si chiama "Inline UDF scalare". Maggiori dettagli qui: https://blogs.msdn.microsoft.com/sqlserverstorageengine/2018/11/07/introducing-scalar-udf-inlining/

[Divulgazione: sono un coautore del documento Froid]


Molto buona! Se capisco correttamente, convertirà automaticamente l'UDF in un ITVF internamente. L'abbiamo fatto per alcuni (w / dichiara / if / else) e abbiamo fatto un bel casino. Abbiamo persino avuto una "colonna" di debug.
crokusek,

1
In realtà non converte l'UDF in un ITVF, ma l'intuizione è corretta. Farlo manualmente a livello di query SQL è davvero complicato per UDF complessi. Froid esegue questa trasformazione sull'algebra relazionale, che evita il disordine :)
Karthik,

@Karthik potresti dare un'occhiata a dba.stackexchange.com/questions/202211/… . Mi piacerebbe davvero sapere come si esibirà Froid nel caso descritto
Roman Pekar,

@Roman ho commentato la tua domanda.
Karthik,

1
Grazie, @Karthik, per il lavoro svolto sul documento Froid e per i tuoi (e gruppi) sforzi nel migliorare l'usabilità degli UDF scalari :-)
Solomon Rutzky,
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.