Apache Spark: impatto di ripartizionamento, ordinamento e memorizzazione nella cache su un join


10

Sto esplorando il comportamento di Spark quando mi unisco a un tavolo. Sto usando Databricks.

Il mio scenario fittizio è:

  1. Leggi una tabella esterna come dataframe A (i file sottostanti sono in formato delta)

  2. Definire il frame di dati B come frame di dati A con solo determinate colonne selezionate

  3. Unisci i frame di dati A e B su colonna1 e colonna2

(Sì, non ha molto senso, sto solo sperimentando per capire la meccanica di base di Spark)

a = spark.read.table("table") \
.select("column1", "column2", "column3", "column4") \
.withColumn("columnA", lower((concat(col("column4"), lit("_"), col("column5")))))

b = a.select("column1", "column2", "columnA")

c= a.join(b, how="left", on = ["column1", "column2"])

Il mio primo tentativo è stato quello di eseguire il codice così com'è (tentativo 1). Ho quindi provato a ripartizionare e memorizzare nella cache (tentativo 2)

a = spark.read.table("table") \
.select("column1", "column2", "column3", "column4") \
.withColumn("columnA", lower((concat(col("column4"), lit("_"), col("column5")))))
.repartition(col("column1"), col("column2")).cache()

Alla fine, ho ripartizionato, ordinato e memorizzato nella cache

 a = spark.read.table("table") \
.select("column1", "column2", "column3", "column4") \
.withColumn("columnA", lower((concat(col("column4"), lit("_"), col("column5")))))
.repartition(col("column1"), col("column2")).sortWithinPartitions(col("column1"), col("column2")).cache()

I rispettivi punti generati sono come allegati.

Le mie domande sono:

  1. Perché nel tentativo 1 la tabella sembra essere memorizzata nella cache anche se la memorizzazione nella cache non è stata specificata in modo esplicito.

  2. Perché InMemoreTableScan è sempre seguito da un altro nodo di questo tipo.

  3. Perché nel tentativo 3 la memorizzazione nella cache sembra avvenire su due livelli?

  4. Perché nel tentativo 3 WholeStageCodegen segue uno (e solo uno) InMemoreTableScan.

tentativo 1

tentativo 2

inserisci qui la descrizione dell'immagine


Sospetto che il lettore DataFrame memorizzi automaticamente nella cache i dati quando l'origine è una tabella esterna. Ho una situazione simile in cui sto leggendo i dati da una tabella del database, mentre è in grado di scaricare la scheda "SQL" in "UI dettagli applicazione" mi mostra il numero di righe da scaricare ma nessun file è stato ancora salvato nella posizione specificata . Immagino che conosca il conteggio perché ha memorizzato nella cache i dati da qualche parte e questo è ciò che appare nel DAG. Se leggi i dati da un file di testo localmente, non vedresti lo stato della cache.
Salim

Risposte:


4

Quello che stai osservando in questi 3 piani è un mix di runtime DataBricks e Spark.

Prima di tutto, durante l'esecuzione di DataBricks runtime 3.3+, la memorizzazione nella cache viene automaticamente abilitata per tutti i file di parquet. Config corrispondente per quello: spark.databricks.io.cache.enabled true

Per la seconda query, InMemoryTableScan si sta verificando due volte perché proprio quando è stato chiamato join, spark ha provato a calcolare il set di dati A e il set di dati B in parallelo. Supponendo che a diversi esecutori siano state assegnate le attività precedenti, entrambi dovranno scansionare la tabella dalla cache (DataBricks).

Per il terzo, InMemoryTableScan non si riferisce alla memorizzazione nella cache in sé. Significa solo che qualunque sia il catalizzatore del piano formato comporta la scansione della tabella cache più volte.

PS: non riesco a visualizzare il punto 4 :)

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.