Motore di esecuzione nativo per Fabric Data Engineering

Il motore di esecuzione nativo costituisce un miglioramento eccezionale per le esecuzioni di processi di Apache Spark in Microsoft Fabric. Questo motore vettorializzato ottimizza le prestazioni e l'efficienza delle query Spark eseguendole direttamente nell'infrastruttura Lakehouse. Grazie alla totale integrazione del motore, non sono necessarie modifiche del codice e si evitano accordi esclusivi con i fornitori. Supporta le API Apache Spark ed è compatibile con Runtime 1.3 (Apache Spark 3.5) e Runtime 2.0 (Apache Spark 4.1) e funziona con i formati Parquet, Delta e CSV. Indipendentemente dalla posizione dei dati all'interno di OneLake o se si accede ai dati tramite collegamenti, il motore di esecuzione nativo ottimizza l'efficienza e le prestazioni.

Il motore di esecuzione nativo aumenta significativamente le prestazioni delle query riducendo al minimo i costi operativi. I risultati effettivi variano in base alle caratteristiche e alla configurazione del carico di lavoro. Il motore è abile nella gestione di un'ampia gamma di scenari di elaborazione dati, che spaziano dall'ingestione di dati di routine, lavori batch e attività ETL (estrazione, trasformazione, caricamento) fino a complesse analisi di data science e interrogazioni interattive dinamiche. Gli utenti traggono vantaggio dall’accelerazione dei tempi di elaborazione, dall’aumento della velocità effettiva e dall'uso ottimizzato delle risorse.

Il motore di esecuzione nativo si basa su due componenti OSS chiave: Velox, una libreria di accelerazione del database C++ introdotta da Meta, e Apache Glutine (incubating), un livello intermedio responsabile dell'offload dell'esecuzione di motori SQL basati su JVM in motori nativi introdotti da Intel.

Gli operatori supportati vengono scaricati da Spark basato su JVM a un percorso di esecuzione C++ vettorializzato, fornendo l'elaborazione con accelerazione SIMD con supporto nativo per i formati Parquet e Delta. Il motore nativo di Fabric mantiene le ottimizzazioni chiave delle query Spark, tra cui l'esecuzione di query adattive (AQE), le riscritture basate sui costi, l'eliminazione delle colonne e il pushdown del predicato, quindi rimangono attivi questi comportamenti di ottimizzazione quando gli operatori vengono esternalizzati. Il motore supporta anche il caricamento parallelo di snapshot Delta e accelera le operazioni che traggono vantaggio dall'ordinamento Z e dal clustering liquido nelle tabelle Delta, offrendo ulteriori miglioramenti delle prestazioni per i layout di dati organizzati.

Quando usare il motore di esecuzione nativo

Il motore di esecuzione nativo offre una soluzione per l'esecuzione di query su set di dati su larga scala; ottimizza le prestazioni usando le funzionalità native delle origini dati sottostanti e riducendo al minimo il sovraccarico tipicamente associato allo spostamento e alla serializzazione dei dati in ambienti Spark tradizionali. Il motore supporta vari operatori e tipi di dati, tra cui aggregazione rollup hash, join annidato con ciclo broadcast (BNLJ) e formati di timestamp precisi. Tuttavia, per sfruttare appieno le funzionalità del motore, è consigliabile considerare i casi d'uso ottimali:

  • Il motore è efficace quando si lavora con i dati in formati Parquet e Delta, che possono essere elaborati in modo nativo ed efficiente.
  • Le query che comportano trasformazioni e aggregazioni complesse traggono notevoli vantaggi dalle funzionalità di elaborazione e vettorizzazione colonnare del motore.
  • Il miglioramento delle prestazioni è particolarmente importante negli scenari in cui le query non attivano il meccanismo di fallback evitando funzionalità o espressioni non supportate.
  • Il motore è particolarmente adatto per le query che richiedono un utilizzo intensivo delle risorse di calcolo, invece che semplici o associate a I/O.

Per informazioni sugli operatori e sulle funzioni supportate dal motore di esecuzione nativo, vedere la Documentazione di Apache Gluten.

Abilitare il motore di esecuzione nativo

Per usare le funzionalità complete del motore di esecuzione nativo durante la fase di anteprima, sono necessarie configurazioni specifiche. Le procedure seguenti illustrano come attivare questa funzionalità per notebook, definizioni processo e interi ambienti Spark.

Abilitare a livello di ambiente

Per garantire un miglioramento uniforme delle prestazioni, abilitare il motore di esecuzione nativo in tutti i processi e i notebook associati all'ambiente:

  1. Passare all'area di lavoro contenente il proprio ambiente e selezionarlo. Se non è stato creato un ambiente, vedere Creare, configurare e usare un ambiente in Fabric.

  2. Sotto Calcolo Spark selezionare Accelerazione.

  3. Selezionare la casella Abilita motore di esecuzione nativo.

  4. Salvare e pubblicare le modifiche.

    Screenshot che mostra come abilitare il motore di esecuzione nativo all'interno dell'elemento ambiente.

Se abilitato a livello di ambiente, tutti i processi e i notebook successivi ereditano l'impostazione. Questa ereditarietà garantisce che qualsiasi nuova sessione o risorsa creata nell'ambiente sfrutti automaticamente le funzionalità di esecuzione avanzate.

Importante

In precedenza, il motore di esecuzione nativo è stato abilitato tramite le impostazioni di Spark all'interno della configurazione dell'ambiente. Il motore di esecuzione nativo può ora essere abilitato più facilmente usando un interruttore nella scheda Accelerazione delle impostazioni dell'ambiente. Per continuare a usarlo, passare alla scheda Accelerazione e attivare l'interruttore. È anche possibile abilitarlo tramite le proprietà di Spark, se preferito.

Abilitare per un notebook o la definizione di un processo Spark

È anche possibile abilitare il motore di esecuzione nativo per un singolo notebook o una definizione di processo Spark, è necessario incorporare le configurazioni necessarie all'inizio dello script di esecuzione:

%%configure 
{ 
   "conf": {
       "spark.native.enabled": "true", 
   } 
} 

Per i notebook, inserire i comandi di configurazione necessari nella prima cella. Per le definizioni del processo Spark, includere le configurazioni all'inizio della definizione del processo Spark. Il motore di esecuzione nativo è integrato con i pool live, quindi, dopo aver abilitato la funzionalità, diventa effettivo immediatamente senza richiedere l'avvio di una nuova sessione.

Controllo a livello di query

I meccanismi per abilitare il motore di esecuzione nativo a livello di tenant, area di lavoro e ambiente, perfettamente integrato con l'interfaccia utente, sono in fase di sviluppo attivo. Nel frattempo, è possibile disabilitare il motore di esecuzione nativo per query specifiche, in particolare se coinvolgono operatori che attualmente non sono supportati (vedere le limitazioni). Per disabilitare, impostare la configurazione Spark spark.native.enabled su false per la cella specifica contenente la query.

%%sql 
SET spark.native.enabled=FALSE; 

Screenshot che mostra come disabilitare il motore di esecuzione nativo all'interno di un notebook.

Dopo aver eseguito la query in cui il motore di esecuzione nativo è disabilitato, è necessario riabilitarlo per le celle successive impostando spark.native.enabled su true. Questo passaggio è necessario perché Spark esegue le celle di codice in sequenza.

%%sql 
SET spark.native.enabled=TRUE; 

Identificare le operazioni eseguite dal motore

Esistono diversi metodi per determinare se un operatore nel processo Apache Spark è stato elaborato usando il motore di esecuzione nativo.

Interfaccia utente di Spark e server cronologia di Spark

Accedere all'interfaccia utente di Spark o al server cronologia di Spark per individuare la query da esaminare. Per accedere all'interfaccia web di Spark, naviga nella definizione del tuo lavoro Spark ed eseguila. Dalla scheda Esecuzioni, selezionare i ... accanto al nome dell'applicazione e selezionare Apri interfaccia utente web di Spark. È anche possibile accedere all'interfaccia utente di Spark dalla scheda Monitor nell'area di lavoro. Selezionare il notebook o la pipeline, nella pagina di monitoraggio è disponibile un collegamento diretto all'interfaccia utente di Spark per i processi attivi.

Screenshot che mostra come passare all'interfaccia utente web Spark.

Nel piano di query visualizzato nell'interfaccia utente di Spark, si devono cercare i nomi di nodo che terminano con il suffisso Transformer, *NativeFileScan, o VeloxColumnarToRowExec. Il suffisso indica che il motore di esecuzione nativo ha eseguito l'operazione. Ad esempio, i nodi possono essere etichettati come RollUpHashAggregateTransformer, ProjectExecTransformer, BroadcastHashJoinExecTransformer, ShuffledHashJoinExecTransformer o BroadcastNestedLoopJoinExecTransformer. Per le origini dati CSV, le analisi native possono essere visualizzate come nodi di analisi di file nativi o trasformatori nell'interfaccia utente di Spark, in modo simile ai nodi di analisi Parquet e Delta.

Screenshot che mostra come controllare la visualizzazione DAG che termina con il suffisso Transformer.

Spiegazione del DataFrame

In alternativa, è possibile eseguire il comando df.explain() nel notebook per visualizzare il piano di esecuzione. All'interno dell'output, cercare i medesimi suffissi di Transformer, *NativeFileScan o VeloxColumnarToRowExec. Questo metodo consente di verificare rapidamente se le operazioni specifiche sono gestite dal motore di esecuzione nativo.

Screenshot che mostra come controllare il piano fisico per la query e scoprire se la query è stata eseguita dal motore di esecuzione nativo.

Avvisi di Fabric Spark Advisor

Fabric Spark Advisor offre visibilità del fallback in tempo reale durante l'esecuzione delle celle del notebook. Quando un operatore o un segmento di piano ritorna a Spark basato su JVM invece della via nativa, Advisor visualizza un avviso direttamente nell'output della cella del notebook, permettendo un'identificazione rapida degli operatori o delle configurazioni non supportati senza uscire dal notebook. È possibile usare questi avvisi per diagnosticare quando l'offload nativo non viene applicato e decidere se modificare la query o la configurazione.

Meccanismo di riserva

In alcuni casi, il motore di esecuzione nativo potrebbe non riuscire a eseguire una query a causa di motivi come funzionalità non supportate. In questi casi, l'operazione ricorre al motore Spark tradizionale. Questo meccanismo di fallback automatico garantisce che non vi sia alcuna interruzione del flusso di lavoro.

Screenshot che mostra il meccanismo di fallback.

Screenshot che mostra come controllare i log associati al meccanismo di fallback.

Monitorare le Query e i DataFrame eseguiti dal motore

Per comprendere meglio il modo in cui il motore di esecuzione nativa viene applicato alle query SQL e alle operazioni del dataframe e per eseguire il drill-down ai livelli di fase e operatore, è possibile fare riferimento all'interfaccia utente spark e al server cronologia Spark per informazioni più dettagliate sull'esecuzione del motore nativo.

Scheda Motore di esecuzione nativo

Puoi navigare sulla nuova scheda "Gluten SQL/DataFrame" per vedere le informazioni sul build di Gluten e i dettagli di esecuzione delle query. La tabella Query fornisce informazioni dettagliate sul numero di nodi in esecuzione nel motore nativo e quelli che rientrano nella JVM per ogni query.

Screenshot che mostra la scheda del motore di esecuzione nativo.

Grafico dell'esecuzione delle query

È anche possibile selezionare la descrizione della query per visualizzare il piano di esecuzione delle query Apache Spark. Il grafico dell'esecuzione fornisce dettagli di esecuzione nativi attraverso le fasi e le rispettive operazioni. I colori di sfondo differenziano i motori di esecuzione: il verde rappresenta il motore di esecuzione nativo, mentre il blu chiaro indica che l'operazione è in esecuzione nel motore JVM predefinito.

Screenshot che mostra il grafico dell'esecuzione di query.

Limiti

Sebbene il motore di esecuzione nativo (NEE) in Fabric migliori significativamente le prestazioni per i lavori Apache Spark, attualmente presenta le seguenti limitazioni. Diversi elementi legati alla correttezza che si applicavano a Runtime 1.3 (Apache Spark 3.5) vengono risolti in Runtime 2.0 (Apache Spark 4.1); Ogni elemento indica il runtime a cui si applica.

Limitazioni esistenti

  • Funzionalità incompatibili di Spark (tutti i runtime): Il motore di esecuzione nativo attualmente non supporta lo streaming strutturato. Se usi funzionalità non supportate, sia direttamente che tramite librerie importate, Spark torna al motore predefinito. Il motore di esecuzione nativo ora supporta UDF Python, UDF Scala e tipi di dati complessi (array, map, struct). Per ulteriori informazioni, vedi UDF Python, UDF Scala e tipi di dati complessi nel motore di esecuzione nativa.

  • Formati file non supportati (tutti i runtime): Il motore di esecuzione nativo non accelera le query contro JSON and XML format. Questi formati di default tornano al normale motore JVM Spark per l'esecuzione. Il parser CSV vettorizato ora supporta CSV.

  • Modalità ANSI (solo runtime 1.3): Su runtime 1.3 (Apache Spark 3.5), il motore di esecuzione nativo non supporta la modalità SQL ANSI. Se abiliti la modalità ANSI SQL, l'esecuzione torna al motore Spark base. Su Runtime 2.0 (Apache Spark 4.1), è supportata la modalità ANSI SQL: gli operatori scaricano il motore nativo e la semantica degli errori ANSI (ad esempio, divisione per zero e cast invalidi) viene applicata in modo coerente con JVM Spark.

  • Disallineamenti tra tipi di filtro di data (tutti i runtime): Per beneficiare dell'accelerazione del motore di esecuzione nativo, assicurati che entrambi i lati di un confronto di data corrispondano nel tipo di dato. Ad esempio, anziché confrontare una DATETIME colonna con un letterale di tipo stringa, effettuarne il cast in modo esplicito come illustrato:

    CAST(order_date AS DATE) = '2024-05-20'
    

Altre considerazioni e limitazioni

Annotazioni

La distribuzione decimale, il fuso orario, round()la map() chiave duplicata e collect_list()collect_set()/gli elementi in questa sezione si applicano a Runtime 1.3 (Apache Spark 3.5) e vengono risolti in Runtime 2.0 (Apache Spark 4.1). Vengono mantenuti per gli utenti che girano ancora su Runtime 1.3.

  • Discrepanza di casting Decimal to Float (Runtime 1.3; risolto in Runtime 2.0): Quando si casta da DECIMAL a FLOAT, Spark preserva la precisione convertendo in una stringa e analizzandola. Su Runtime 1.3, NEE (tramite Velox) esegue una trasmissione diretta dalla rappresentazione interna int128_t , il che può causare discrepanze di arrotondamento.

  • Errori di configurazione del fuso orario (Runtime 1.3; risolti in Runtime 2.0): Su Runtime 1.3, impostare un fuso orario non riconosciuto in Spark fa fallire il lavoro sotto NEE, mentre Spark JVM lo gestisce con eleganza. Per esempio:

    "spark.sql.session.timeZone": "-08:00"  // May cause failure under NEE on Runtime 1.3
    
  • Comportamento di arrotondamento incoerente (Runtime 1.3; risolto in Runtime 2.0): A Runtime 1.3, la round() funzione si comporta diversamente in NEE a causa della dipendenza su std::round, che non replica la logica di arrotondamento di Spark. Questa differenza può portare a incoerenze numeriche nei risultati dell'arrotondamento.

  • Funzione di check-in map() duplicata del tasto mancante (Runtime 1.3; risolta in Runtime 2.0): Quando spark.sql.mapKeyDedupPolicy è impostata su EXCEPTION, Spark genera un errore per chiavi duplicate. A runtime 1.3, NEE salta questo controllo e permette che la query abbia successo in modo errato. Su Runtime 2.0, NEE aumenta DUPLICATED_MAP_KEY costantemente con JVM Spark.
    Esempio:

    SELECT map(1, 'a', 1, 'b'); -- Should fail with duplicate keys
    
  • Variazione d'ordine in collect_list() con ordinamento (Runtime 1.3; risolto in Runtime 2.0): Quando si usa DISTRIBUTE BY e SORT BY, Spark preserva l'ordine degli elementi in collect_list(). Su Runtime 1.3, il NEE può restituire valori in un ordine diverso a causa di differenze di mescolamento, il che può portare a aspettative disadattate per la logica sensibile all'ordine.

  • Disadattamento intermedio di tipo per collect_list() / collect_set() (Runtime 1.3; risolto in Runtime 2.0): Su Runtime 1.3, Spark usa BINARY come tipo intermedio per queste aggregazioni, mentre NEE usa ARRAY. Questa mancata corrispondenza potrebbe causare problemi di compatibilità durante la pianificazione o l'esecuzione delle query.

  • Endpoint privati gestiti richiesti per l'accesso allo storage (tutti i runtime): Quando il Native Execution Engine (NEE) è abilitato, e se i job Spark cercano di accedere a un account di storage usando un endpoint privato gestito, devi configurare endpoint privati gestiti separati sia per il Blob (blob.core.windows.net) che per quello DFS / File System (dfs.core.windows.net), anche se puntano allo stesso account di storage. Non puoi riutilizzare un singolo endpoint per entrambi. Questa limitazione potrebbe richiedere una configurazione di rete aggiuntiva quando si abilita il motore di esecuzione nativo in uno spazio di lavoro che ha gestiti endpoint privati verso account di archiviazione.