Spark SQL 的資料跳過

資料跳過可大幅提高 SQL 查詢的效能,方法是基於與每一個物件相關聯的摘要 meta 資料,跳過不相關的資料物件或檔案。

資料跳過會使用開放程式碼 Xskipper 程式庫,透過 Apache Spark 來建立、管理及部署資料跳過索引。 請參閱 Xskipper-可延伸資料跳過架構

如需如何使用 Xskipper 的相關詳細資料,請參閱:

除了 Xskipper 中的開放程式碼特性之外,還提供了下列特性:

地理空間資料跳過

使用 時空庫中的 地理空間函數 來查詢地理空間資料集時,您也可以使用資料跳過。

  • 若要在具有緯度及經度直欄的資料集內從資料跳過中獲益,您可以在緯度及經度直欄收集 min/max 索引。
  • 可以使用內建 Xskipper 外掛程式,在具有幾何佈置直欄 (UDT 直欄) 的資料集中使用資料跳過。

下面幾節將向您顯示如何使用地理空間外掛程式。

設定地理空間外掛程式

若要使用外掛程式,請使用「登錄」模組載入相關實作:

  • 若為 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)
    
  • 若為 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')
    

索引建置

若要建置索引,您可以使用 addCustomIndex API:

  • 若為 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)
    
  • 若為 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)
    

支援的函數

受支援的地理空間函數清單包括:

  • ST_Distance
  • ST_Intersects
  • ST_Contains
  • ST_Equals
  • ST_Crosses
  • ST_Touches
  • ST_Within
  • ST_Overlaps
  • ST_EnvelopesIntersect
  • ST_IntersectsInterior

加密索引

如果您使用 Parquet meta 資料儲存庫,則可使用「Parquet 模組化加密 (PME)」選擇性地加密 meta 資料。 將 meta 資料本身儲存為 Parquet 資料集即會達成此目的,如此即可使用 PME 來加密它。 此特性適用於所有輸入格式,例如,以 CSV 格式儲存的資料集可以使用 PME 加密其 meta 資料。

在下一節中,除非另有說明,否則在提到標底、直欄等時,這些項目皆與 meta 資料物件相關,而非與索引資料集中的物件相關。

索引加密是按下列方式模組化及精細化:

  • 每個索引皆可加密(使用每個索引的金鑰精度)或保留為純文字
  • 標底 + 物件名稱直欄:
    • 除了其他項目以外,本身是 Parquet 檔的 meta 資料物件的標底直欄還包含:
      • meta 資料物件的綱目,顯示所收集全部索引的類型、參數及直欄名稱。 例如,您可以瞭解在直欄 city 上定義的 BloomFilter,其誤判機率為 0.1
      • 原始資料集的完整路徑或表格名稱(如果是 Hive meta 儲存庫表格)。
    • 物件名稱直欄會儲存所有索引物件的名稱。
  • 標底 + meta 資料直欄可以:
    • 皆使用相同金鑰進行加密。 這是預設值。 在此情況下,包含 meta 資料的 Parquet 物件的純文字標底配置處於加密標底模式,且物件名稱直欄會使用選取的金鑰來加密。

    • 皆為純文字。 在此情況下,包含 meta 資料的 Parquet 物件處於純文字標底模式,且物件名稱直欄不會加密。

      如果至少有一個索引標示為已加密,則不論是否已啟用純文字標底模式,皆必須配置標底金鑰。 如果已設定純文字標底,則標底金鑰僅用於防竄改。 請注意,在該情況下,物件名稱直欄沒有防竄改。

      如果已配置標底金鑰,則必須加密至少一個索引。

在使用索引加密之前,您應該先檢查 PME 上的說明文件,並確定您熟悉這些概念。

使用索引加密時,每當在任何 Xskipper API 中配置 key 時,它一律是 NEVER the key itself 標籤。

若要使用索引加密,請執行下列動作:

  1. 遵循所有步驟,以確定已啟用 PME。 請參閱 PME

  2. 執行所有 一般 PME 配置,包括金鑰管理配置。

  3. 為資料集建立加密 meta 資料:

    1. 遵循建立 meta 資料的一般流程。
    2. 配置標底金鑰。 如果您想要設定純文字標底 + 物件名稱直欄,請將 io.xskipper.parquet.encryption.plaintext.footer 設為 true (請參閱下面的範例)。
    3. IndexBuilder 中,針對您要加密的每一個索引,新增要用於該索引的金鑰標籤。

    若要在查詢期間使用 meta 資料或重新整理現有 meta 資料,除了確保可存取金鑰 (字面上是讀取已加密資料集所需的相同配置) 所需的 一般 PME 設定之外,不需要任何設定。

範例

下列範例顯示 meta 資料建立作業,使用名為 k1 的金鑰作為標底 + 物件名稱金鑰,並使用名為 k2 的金鑰作為金鑰來加密 MinMax for temp,同時建立 ValueList for city(以純文字形式保留)。

  • 若為 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)
    
  • 若為 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)
    

如果要讓標底 + 物件名稱保留為純文字模式(如上所述),您需要新增配置參數:

  • 若為 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)
    
  • 若為 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)
    

支援較舊的 meta 資料

Xskipper 可無縫地支援 MetaIndexManager 建立的較舊 meta 資料。 較舊的 meta 資料可以用來跳過,因為下次重新整理作業會自動執行對 Xskipper meta 資料的更新。

如果您在列出索引或執行 describeIndex 作業時在索引前面看到 DEPRECATED_SUPPORTED,則 meta 資料版本已淘汰,但仍受支援,且跳過將可運作。 下次重新整理作業會自動更新 meta 資料。