Spark SQL 的資料跳過
資料跳過可大幅提高 SQL 查詢的效能,方法是基於與每一個物件相關聯的摘要 meta 資料,跳過不相關的資料物件或檔案。
資料跳過會使用開放程式碼 Xskipper 程式庫,透過 Apache Spark 來建立、管理及部署資料跳過索引。 請參閱 Xskipper - 可延伸的資料跳過架構。
如需如何使用 Xskipper 的相關詳細資料,請參閱:
除了 Xskipper 中的開放程式碼特性之外,還提供了下列特性:
地理空間資料跳過
使用時空性程式庫中的地理空間函數來查詢地理空間資料集時,您也可以使用資料跳過。
- 若要在具有緯度及經度直欄的資料集內從資料跳過中獲益,您可以在緯度及經度直欄收集 min/max 索引。
- 透過使用內建 Xskipper 外掛程式,即可在具有幾何直欄(UDT 直欄)的資料集中使用資料跳過。
下面幾節將向您顯示如何使用地理空間外掛程式。
設定地理空間外掛程式
若要使用外掛程式,請使用「登錄」模組載入相關實作。 請注意,您只能在採用 Apache Spark技術的 IBM Analytics Engine 中使用 Scala ,而不能在 Watson Studio中使用。
若為 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。 請注意,您只能在採用 Apache Spark技術的 IBM Analytics Engine 中使用 Scala ,而不能在 Watson Studio中使用。
若為 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 資料物件的綱目,顯示所收集全部索引的類型、參數及直欄名稱。 例如,您可以瞭解到,
BloomFilter是在直欄city中定義,其誤肯定機率為0.1。 - 原始資料集的完整路徑或表格名稱(如果是 Hive meta 儲存庫表格)。
- meta 資料物件的綱目,顯示所收集全部索引的類型、參數及直欄名稱。 例如,您可以瞭解到,
- 物件名稱直欄會儲存所有索引物件的名稱。
- 除了其他項目以外,本身是 Parquet 檔的 meta 資料物件的標底直欄還包含:
- 標底 + meta 資料直欄可以:
皆使用相同金鑰進行加密。 這是預設值。 在此情況下,包含 meta 資料的 Parquet 物件的純文字標底配置處於加密標底模式,且物件名稱直欄會使用選取的金鑰來加密。
皆為純文字。 在此情況下,包含 meta 資料的 Parquet 物件處於純文字標底模式,且物件名稱直欄不會加密。
如果至少有一個索引標示為已加密,則不論是否已啟用純文字標底模式,皆必須配置標底金鑰。 如果已設定純文字標底,則標底金鑰僅用於防竄改。 請注意,在該情況下,物件名稱直欄沒有防竄改。
如果已配置標底金鑰,則必須加密至少一個索引。
使用索引加密之前,您應該檢查 PME 上的說明文件,並確定您熟悉概念。
若要使用索引加密,請執行下列動作:
遵循所有步驟,以確定已啟用 PME。 請參閱 PME。
執行所有一般 PME 配置,包括「金鑰管理」配置。
為資料集建立加密 meta 資料:
- 遵循建立 meta 資料的一般流程。
- 配置標底金鑰。 如果您想要設定純文字標底 + 物件名稱直欄,請將
io.xskipper.parquet.encryption.plaintext.footer設為true(請參閱下面的範例)。 - 在
IndexBuilder中,針對您要加密的每個索引,新增要用於該索引的索引鍵標籤。
若要在查詢時間期間使用 meta 資料或要重新整理現有 meta 資料,除了確保可存取金鑰所需的一般 PME 設定(確實需要相同配置才能讀取加密資料集)以外,無需任何設定。
範例
下列範例顯示建立 meta 資料的方法:使用名為 k1 的金鑰作為標底 + 物件名稱金鑰,使用名為 k2 的金鑰作為針對 temp 加密 MinMax 的金鑰,同時還針對 city 建立保留為純文字的 ValueList。 請注意,您只能在採用 Apache Spark技術的 IBM Analytics Engine 中使用 Scala ,而不能在 Watson Studio中使用。
若為 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)
資料跳過與結合(僅適用於 Spark 3)
透過 Spark 3,您可以在諸如以下的結合查詢中使用資料跳過:
SELECT *
FROM orders, lineitem
WHERE l_orderkey = o_orderkey and o_custkey = 800
此範例顯示基於 TPC-H 基準性能測試綱目(請參閱 TPC-H)的星狀綱目,其中 lineitem 是事實表格且包含許多記錄,而 orders 表格則是維度表格,其與事實表格相比,具有的記錄數目相對較少。
上述查詢在包含少量記錄的 orders 表格中具有述詞,這意味著使用 min/max 將不會從資料跳過中獲益很多。
動態資料跳過 是一項特性,可讓您根據 orders 表格中的條件先擷取相關的 l_orderkey 值,然後在 l_orderkey 中使用它來推入述詞,以使用資料跳過索引來過濾無關的物件,從而讓諸如以上的查詢從資料跳過中獲益。
若要使用此特性,請啟用下列最佳化規則。 請注意,您只能在採用 Apache Spark技術的 IBM Analytics Engine 中使用 Scala ,而不能在 Watson Studio中使用。
若為 Scala:
import com.ibm.spark.implicits. spark.enableDynamicDataSkipping()若為 Python:
from sparkextensions import SparkExtensions SparkExtensions.enableDynamicDataSkipping(spark)
然後,照常使用 Xskipper API,查詢即會從使用資料跳過中獲益。
例如,在上述查詢中,使用 min/max 來檢索 l_orderkey 將允許跳過 lineitem 表格,從而會改善查詢效能。
支援較舊的 meta 資料
Xskipper 可無縫地支援 MetaIndexManager 建立的較舊 meta 資料。 較舊的 meta 資料可以用來跳過,因為下次重新整理作業會自動執行對 Xskipper meta 資料的更新。
列出索引或執行 describeIndex 作業時,如果在索引前面看到 DEPRECATED_SUPPORTED,則表示 meta 資料版本已淘汰,但仍受支援,且跳過將會正常運作。 下次重新整理作業會自動更新 meta 資料。