Skipping dei dati per Spark SQL

Lo skipping dei dati può aumentare in modo significativo le prestazioni delle query SQL ignorando oggetti di dati irrilevanti o file basati su un riepilogo dei metadati associati ad ogni oggetto.

Lo skipping dei dati utilizza la libreria Xskipper open source per la creazione, la gestione e la distribuzione degli indici di sci dati con Apache Spark. Consultare Xskipper - An Extensible Data Skipping Framework.

Per maggiori dettagli su come lavorare con Xskipper vedi:

Oltre alle funzioni open source in Xskipper sono disponibili anche le seguenti funzioni:

Skipping dei dati geospaziali

È inoltre possibile utilizzare lo skipping dei dati quando si interrogano i dataset geospaziali utilizzando funzioni geospaziali dalla libreria spato-temporale.

  • Per beneficiare dello skipping dei dati nei dataset con colonne di latitudine e longitudine, è possibile raccogliere gli indici min / max sulle colonne di latitudine e longitudine.
  • Lo skipping dei dati può essere utilizzato nei dataset con una colonna di geometria (una colonna UDT) utilizzando un plugin Xskipper integratointegrato.

Le sezioni successive mostrano di lavorare con il plugin geospaziale.

Impostazione del plugin geospaziale

Per utilizzare un plugin, caricare le implementazioni rilevanti utilizzando il modulo Registrazione:

  • Per Scala:

    import com.ibm.xskipper.stmetaindex.filter.STMetaDataFilterFactory
    import com.ibm.xskipper.stmetaindex.index.STIndexFactory
    import com.ibm.xskipper.stmetaindex.translation.parquet.{STParquetMetaDataTranslator, STParquetMetadatastoreClauseTranslator}
    import io.xskipper._
    
    Registration.addIndexFactory(STIndexFactory)
    Registration.addMetadataFilterFactory(STMetaDataFilterFactory)
    Registration.addClauseTranslator(STParquetMetadatastoreClauseTranslator)
    Registration.addMetaDataTranslator(STParquetMetaDataTranslator)
    
  • Per Python:

    from xskipper import Xskipper
    from xskipper import Registration
    
    Registration.addMetadataFilterFactory(spark, 'com.ibm.xskipper.stmetaindex.filter.STMetaDataFilterFactory')
    Registration.addIndexFactory(spark, 'com.ibm.xskipper.stmetaindex.index.STIndexFactory')
    Registration.addMetaDataTranslator(spark, 'com.ibm.xskipper.stmetaindex.translation.parquet.STParquetMetaDataTranslator')
    Registration.addClauseTranslator(spark, 'com.ibm.xskipper.stmetaindex.translation.parquet.STParquetMetadatastoreClauseTranslator')
    

Edificio dell'indice

Per costruire un indice è possibile utilizzare l'API addCustomIndex :

  • Per Scala:

    import com.ibm.xskipper.stmetaindex.implicits._
    
    // index the dataset
    val xskipper = new Xskipper(spark, dataset_path)
    
    xskipper
      .indexBuilder()
      // using the implicit method defined in the plugin implicits
      .addSTBoundingBoxLocationIndex("location")
      // equivalent
      //.addCustomIndex(STBoundingBoxLocationIndex("location"))
      .build(reader).show(false)
    
  • Per Python:

    xskipper = Xskipper(spark, dataset_path)
    
    # adding the index using the custom index API
    xskipper.indexBuilder() \
            .addCustomIndex("com.ibm.xskipper.stmetaindex.index.STBoundingBoxLocationIndex", ['location'], dict()) \
            .build(reader) \
            .show(10, False)
    

Funzioni supportate

L'elenco delle funzioni geospaziali supportate include quanto segue:

  • ST_Distanza
  • ST_Intersects
  • ST_Contiene
  • ST_Equals
  • ST_Crosses
  • ST_Touches
  • ST_Within
  • ST_Overlaps
  • ST_EnvelopesIntersect
  • ST_IntersectsInterior

Codifica degli indici

Se si utilizza un negozio di metadati Parquet, i metadati possono opzionalmente essere crittografati utilizzando Parquet Modular Encryption (PME). Questo si ottiene memorizzando i metadati stessi come un dataset Parquet e quindi PME può essere utilizzato per crittografarlo. Questa funzione si applica a tutti i formati di input, ad esempio, un dataset memorizzato in formato CSV può avere i suoi metadati crittografati utilizzando PME.

Nella sezione seguente, a meno che non sia specificato diversamente, quando si riferiscono a footers, colonne e così via, questi sono rispetto agli oggetti metadati, e non agli oggetti nel dataset indicizzato.

La crittografia dell'indice è modulare e granulare nel seguente modo:

  • Ogni indice può essere crittografato (con una granularità chiave per indice) o in chiaro di sinistra
  • Piè di pagina + nome oggetto:
    • Colonna piana dell'oggetto metadati che di per sé è un file di Parquet contiene, tra le altre cose:
      • Schema dell'oggetto metadati, che rivela i tipi, i parametri e i nomi delle colonne per tutti gli indici raccolti. Ad esempio, si può imparare che un BloomFilter è definito sulla colonna city con una probabilità falsata di 0.1.
      • Percorso completo al dataset originale o un nome da tavolo in caso di tabella metastore Hive.
    • La colonna nome oggetto memorizza i nomi di tutti gli oggetti indicizzati.
  • La colonna dei metadati + può essere:
    • Entrambi crittografati usando la stessa chiave. Questo è il valore predefinito. In questo caso, la configurazione del footer di testo semplice per gli oggetti Parquet comprendente i metadati in modalità footer crittografata e la colonna nome oggetto viene crittografata utilizzando la chiave selezionata.

    • Sia in testo semplice. In questo caso, gli oggetti Parquet che comprendono i metadati sono in modalità di testo semplice e la colonna nome oggetto non è crittografata.

      Se almeno un indice è contrassegnato come crittografato, allora un tasto di piè di pagina deve essere configurato indipendentemente dal fatto che la modalità piè di testo semplice sia abilitata o meno. Se si imposta un footer di testo semplice allora la chiave di piè di pagina viene utilizzata solo per la manomissione. Da notare che in quel caso la colonna del nome oggetto non è manomissione.

      Se un tasto di piè di pagina è configurato, allora almeno un indice deve essere crittografato.

Prima di utilizzare la crittografia dell'indice, è necessario controllare la documentazione su PME e assicurarsi di conoscere i concetti.

Quando si utilizza la crittografia dell'indice, ogni qualvolta un key è configurato in qualsiasi API Xskipper, è sempre l'etichetta NEVER the key itself.

Per utilizzare la crittografia dell'indice:

  1. Segui tutti i passaggi per assicurarsi che PME sia abilitato. Vedere PME.

  2. Eseguire tutte le configurazioni regolari PME, incluse le configurazioni di Key Management.

  3. Creare metadati crittografati per un dataset:

    1. Segui il flusso regolare per la creazione dei metadati.
    2. Configurare un tasto di piè di pagina. Se desideri impostare una colonna di testo semplice + colonna nome oggetto, impostare io.xskipper.parquet.encryption.plaintext.footer su true (Vedi i campioni sotto).
    3. In IndexBuilder, per ogni indice che si desidera cifrare, aggiungere l'etichetta della chiave da utilizzare per quell' indice.

    Per utilizzare i metadati durante il tempo della query o per aggiornare i metadati esistenti, non è necessario alcun setup diverso dal setup di regolare PME necessario per assicurarsi che le chiavi siano accessibili (letteralmente la stessa configurazione necessaria per leggere un dataset crittografato).

Esempi

I seguenti campioni mostrano la creazione di metadati utilizzando una chiave denominata k1 come chiave nome oggetto + e una chiave denominata k2 come chiave per crittografare un MinMax per temp, creando anche un ValueList per city, che viene lasciato in chiaro testo.

  • Per Scala:

    // index the dataset
    val xskipper = new Xskipper(spark, dataset_path)
    // Configuring the JVM wide parameters
    val jvmComf = Map(
      "io.xskipper.parquet.mdlocation" -> md_base_location,
      "io.xskipper.parquet.mdlocation.type" -> "EXPLICIT_BASE_PATH_LOCATION")
    Xskipper.setConf(jvmConf)
    // set the footer key
    val conf = Map(
      "io.xskipper.parquet.encryption.footer.key" -> "k1")
    xskipper.setConf(conf)
    xskipper
      .indexBuilder()
      // Add an encrypted MinMax index for temp
      .addMinMaxIndex("temp", "k2")
      // Add a plaintext ValueList index for city
      .addValueListIndex("city")
      .build(reader).show(false)
    
  • Per Python

    xskipper = Xskipper(spark, dataset_path)
    # Add JVM Wide configuration
    jvmConf = dict([
    ("io.xskipper.parquet.mdlocation", md_base_location),
    ("io.xskipper.parquet.mdlocation.type", "EXPLICIT_BASE_PATH_LOCATION")])
    Xskipper.setConf(spark, jvmConf)
    # configure footer key
    conf = dict([("io.xskipper.parquet.encryption.footer.key", "k1")])
    xskipper.setConf(conf)
    # adding the indexes
    xskipper.indexBuilder() \
            .addMinMaxIndex("temp", "k1") \
            .addValueListIndex("city") \
            .build(reader) \
            .show(10, False)
    

Se si desidera che il piè di pagina + nome oggetto venga lasciato in modalità testo semplice (come detto sopra), è necessario aggiungere il parametro di configurazione:

  • Per Scala:

    // index the dataset
    val xskipper = new Xskipper(spark, dataset_path)
    // Configuring the JVM wide parameters
    val jvmComf = Map(
      "io.xskipper.parquet.mdlocation" -> md_base_location,
      "io.xskipper.parquet.mdlocation.type" -> "EXPLICIT_BASE_PATH_LOCATION")
    Xskipper.setConf(jvmConf)
    // set the footer key
    val conf = Map(
      "io.xskipper.parquet.encryption.footer.key" -> "k1",
      "io.xskipper.parquet.encryption.plaintext.footer" -> "true")
    xskipper.setConf(conf)
    xskipper
      .indexBuilder()
      // Add an encrypted MinMax index for temp
      .addMinMaxIndex("temp", "k2")
      // Add a plaintext ValueList index for city
      .addValueListIndex("city")
      .build(reader).show(false)
    
  • Per Python

    xskipper = Xskipper(spark, dataset_path)
    # Add JVM Wide configuration
    jvmConf = dict([
    ("io.xskipper.parquet.mdlocation", md_base_location),
    ("io.xskipper.parquet.mdlocation.type", "EXPLICIT_BASE_PATH_LOCATION")])
    Xskipper.setConf(spark, jvmConf)
    # configure footer key
    conf = dict([("io.xskipper.parquet.encryption.footer.key", "k1"),
    ("io.xskipper.parquet.encryption.plaintext.footer", "true")])
    xskipper.setConf(conf)
    # adding the indexes
    xskipper.indexBuilder() \
            .addMinMaxIndex("temp", "k1") \
            .addValueListIndex("city") \
            .build(reader) \
            .show(10, False)
    

Supporto per i metadati più anziani

Xskipper supporta metadati meno recenti creati da MetaIndexManager senza soluzione di continuità. I metadati più vecchi possono essere utilizzati per lo sci come aggiornamenti ai metadati Xskipper vengono effettuati automaticamente dalla prossima operazione di aggiornamento.

Se si vede DEPRECATED_SUPPORTED davanti ad un indice quando elencare gli indici o eseguire un'operazione describeIndex, la versione dei metadati è obsoleta ma è comunque supportata e lo skipping funzionerà. La prossima operazione di aggiornamento aggiornerà automaticamente i metadati.