0 / 0
영어 버전 문서로 돌아가기

Spark SQL의 데이터 스키핑

마지막 업데이트 날짜: 2024년 11월 21일
Spark SQL의 데이터 스키핑

데이터 스키핑은 각 데이터 오브젝트와 연관되는 요약 메타데이터를 기반으로 상관없는 데이터 오브젝트 또는 파일을 건너뜀으로써 SQL 조회의 성능을 현저히 향상시킬 수있습니다.

데이터 스키핑은 Apache Spark에서 데이터 스키핑 인덱스를 작성, 관리, 배치하기 위한 오픈 소스 Xskipper 라이브러리를 사용합니다. Xskipper - 확장형 데이터 스키핑 프레임워크를 참조하십시오.

Xskipper 작업 방법에 대한 자세한 정보는 다음을 참조하십시오.

Xskipper에서 오픈 소스 기능 외에도, 다음 기능도 사용할 수 있습니다.

지리공간 데이터 건너뛰기

공간적-시간적 라이브러리에서 지리공간 함수를 사용하여 지리공간 데이터 세트를 조회할 때 데이터 건너뛰기를 사용할 수도 있습니다.

  • 경도 및 위도 열이 있는 데이터 세트에서 데이터 스키핑의 해택을 얻기 위해 위도 및 경도 열에서 최소/최대 인덱스를 수집할 수 있습니다.
  • 데이터 건너뛰기는 내장 Xskipper 플러그인을 사용하여 기하학적 열(UDT 열)이 있는 데이터셋에서 사용할 수 있습니다.

다음 섹션에서는 지리공간 플러그인에 대한 작업을 수행하는 방법을 보여줍니다.

지리공간 플러그인 설정

플러그인을 사용하려면 등록 모듈을 사용하여 관련 구현을 로드하십시오. Apache Spark 기반 IBM Analytics Engine 애플리케이션에서만 Scala를 사용할 수 있으며 watsonx.ai 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를 사용할 수 있으며 watsonx.ai 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 메타데이터 저장소를 사용하는 경우 선택적으로 PME(Parquet Modular Encryption)를 사용하여 메타데이터를 암호화할 수 있습니다. 메타데이터 자체를 Parquet 데이터 세트로 저장하면 됩니다. 그러면 PME를 사용하여 암호화할 수 있습니다. 이 기능은 모든 입력 형식(예: PME를 사용하여 메타데이터를 암호화할 수 있는, CSV 형식으로 저장된 데이터 세트)에 적용됩니다.

다음 섹션에서는 별도로 언급하지 않는 한, 바닥글, 열 등을 참조할 때 인덱싱된 데이터 세트의 오브젝트가 아니라 메타데이터 오브젝트와 관련됩니다.

인덱스 암호화는 다음과 같은 방식에서 모듈식으로 세부화되어 있습니다.

  • 각 인덱스는 암호화되거나 (인덱스당 키 단위로) 일반 텍스트로 남아 있을 수 있습니다.
  • 바닥글 + 오브젝트 이름 열:
    • 자체적으로 Parquet 파일인 메타데이터 오브젝트의 바닥글 열은 특히 다음을 포함합니다.
      • 수집된 모든 인덱스에 대한 유형, 매개변수, 열 이름을 표시하는 메타데이터 오브젝트의 스키마. 예를 들어, BloomFilter이(가) 0.1의 긍정 오류 확률로 city 열에 정의되어 있음을 알 수 있습니다.
      • 원래 데이터 세트에 대한 전체 경로 또는 Hive 메타저장소 테이블의 경우 테이블 이름
    • 오브젝트 이름 열은 인덱싱된 모든 오브젝트 이름을 저장합니다.
  • 바닥글 + 메타데이터 열은 다음과 같을 수 있습니다.
    • 둘 다 동일한 키를 사용하여 암호화됩니다. 이는 기본값입니다. 이 경우 메타데이터를 구성하는 Parquet 오브젝트의 평문 바닥글 구성은 암호화된 바닥글 모드로 암호화되며 오브젝트 이름 열은 선택한 키를 사용하여 암호화됩니다.

    • 둘 다 일반 텍스트입니다. 이 경우 메타데이터를 구성하는 Parquet 오브젝트는 평문 바닥글 모드이고, 오브젝트 이름 열은 암호화되지 않습니다.

      하나 이상의 인덱스가 암호화됨으로 표시되는 경우 평문 바닥글 모드의 사용 여부에 상관없이 바닥글 키를 구성해야 합니다. 평문 바닥글이 설정된 경우 변조 방지를 위해서만 바닥글 키가 사용됩니다. 이 경우 오브젝트 이름 열에는 변조 방지 기능이 적용되지 않습니다.

      바닥글 키가 구성된 경우 하나 이상의 인덱스를 암호화해야 합니다.

인덱스 암호화를 사용하기 전에 PME에서 문서를 확인하고 개념을 잘 알고 있는지 확인해야 합니다.

중요: 색인 암호화를 사용할 때 Xskipper API에서 key 가 구성될 때마다 이는 항상 `키 자체를 사용하지 않음 ` 레이블입니다.

인덱스 암호화를 사용하려면 다음을 수행하십시오.

  1. 모든 단계를 수행하여 PME를 사용하도록 하십시오. PME를 참조하십시오.

  2. 키 관리 구성을 포함하여 모든 정기적 PME 구성을 수행하십시오.

  3. 데이터 세트에 대한 암호화된 메타데이터를 작성하십시오.

    1. 메타데이터 작성 시 일반 플로우를 따르십시오.
    2. 푸터 키를 구성하십시오. 일반 텍스트 푸터 +오브젝트 이름 열을 설정하려면 io.xskipper.parquet.encryption.plaintext.footer을(를) true(으)로 설정하십시오(아래 샘플 참조).
    3. IndexBuilder에서 암호화할 각 인덱스에 대해 해당 인덱스에 사용할 키의 레이블을 추가하십시오.

    조회 시간 동안 메타데이터를 사용하거나 기존 메타데이터를 새로 고치려는 경우, 키가 액세스 가능한지 확인하는 데 필요한 정기적 PME 설정 이외에 다른 설정은 필요하지 않습니다(문자 그대로 암호화된 데이터 세트를 읽는 데 필요한 동일한 구성).

샘플

다음 샘플은 k1 키를 푸터 + 오브젝트 이름 키로 사용하고 k2 키를 temp에 대한 MinMax을(를) 암호화하기 위한 키로 사용하여 메타데이터를 작성하는 한편 일반 텍스트로 남아 있는 city에 대한 ValueList을(를) 작성하는 내용을 보여줍니다. Apache Spark 기반 IBM Analytics Engine 애플리케이션에서만 Scala를 사용할 수 있으며 watsonx.ai 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은 사실 테이블이고 많은 레코드를 포함하는 반면, 주문 테이블은 사실 테이블과 비교하여 상대적으로 적은 수의 레코드가 있는 차원 테이블입니다.

위 조회에는 적은 수의 레코드를 포함하는 주문 테이블에 술어가 있으며, 이는 min/max를 사용해도 데이터 스키핑 효과가 크지 않음을 의미합니다.

동적 데이터 건너뛰기는 먼저 orders 테이블의 조건을 기반으로 관련 l_orderkey 값을 추출한 후 이를 사용하여 상관없는 오브젝트를 필터하기 위해 데이터를 사용하는 데이터를 사용하는 l_orderkey에서 술어를 푸시하여 위와 같은 조회가 데이터를 건너뛰는 혜택을 받을 수 있도록 하는 기능입니다.

이 기능을 사용하려면 다음 최적화 규칙을 사용으로 설정하십시오. Apache Spark 기반 IBM Analytics Engine 애플리케이션에서만 Scala를 사용할 수 있으며 watsonx.ai Studio에서는 사용할 수 없습니다.

  • Scala의 경우:

      import com.ibm.spark.implicits.
    
      spark.enableDynamicDataSkipping()
    
  • Python의 경우:

        from sparkextensions import SparkExtensions
    
        SparkExtensions.enableDynamicDataSkipping(spark)
    

그런 다음, 평상시대로 Xskipper API를 사용합니다. 그러면 조회에서 데이터 스키핑의 이점을 활용할 수 있습니다.

예를 들어, 위의 조회에서 최소/최대를 사용하여 l_orderkey을(를) 색인화하면 lineitem 테이블에서 건너뛸 수 있으며 조회 성능이 향상됩니다.

이전 메타데이터에 대한 지원

Xskipper는 MetaIndexManager에서 작성한 이전 메타데이터를 원활하게 지원합니다. 다음 새로 고치기 오퍼레이션에 의해 Xskipper 메타데이터에 대한 업데이트가 자동으로 수행되므로 이전 메타데이터를 스키핑에 사용할 수 있습니다.

인덱스를 나열하거나 describeIndex 조작을 실행할 때 인덱스 앞에 DEPRECATED_SUPPORTED이(가) 표시되면 메타데이터 버전은 더 이상 사용되지 않지만 여전히 지원되며 건너뛰기가 작동됩니다. 다음 새로 고치기 오퍼레이션은 메타데이터를 자동으로 업데이트합니다.