Introdução aos casos de uso do Spark watsonx.data

É possível executar casos de uso do Spark para watsonx.data usando amostras Python . Todas as amostras são gravadas usando APIs Spark Python .

Antes de iniciar

Antes de poder executar casos de uso do Spark para watsonx.data, deve-se:

  • Provisione uma instância do IBM watsonx.data com base no ambiente (watsonx.data no CPD, watsonx.data on Cloud) escolhido.
  • Provisione uma instância do IBM Analytics Engine em um cluster Cloud Pak for Data. Consulte “Provisionamento de uma instância ”.
  • Crie um volume no Cloud Pak for Data Consulte Criar um Cloud Pak for Data

Sobre o caso de uso de amostra

O arquivo de amostra demonstra as seguintes funções:

Acessando tabelas a partir de watsonx.data
: a seção Criar um banco de dados no catálogo Lakehouse do arquivo python de amostra cria um banco de dados demodb na instância watsonx.data configurada com um catálogo denominado lakehouse. O demodb é configurado para armazenar todos os dados e metadados no Cloud Object Storage bucket lakehouse-bucket. Ele também cria uma tabela iceberg testTable e a acessa..


Importação de dados para o watsonx.data
: A seção “Importar dados em formato Parquet para uma tabela do Lakehousedo arquivo Python de exemplo permite importar dados nos formatos Parquet e CSV de um Spark-VOL para uma tabela do watsonx.data. Os dados de exemplo no formato Parquet são inseridos do volume na tabela watsonx.data yellow_taxi_2022 (baixada na etapa 2 ). A seção “Ingestão de dados do Parquet em uma tabela do Lakehouse” do arquivo Python de exemplo também mostra a ingestão de dados no formato CSV do spark-vol para a tabela zipcode no banco de dados demodb. Para obter instruções sobre como acessar os dados de exemplo e carregá-los no volume, consulte a seção “Inserindo dados de exemplo no volume ‘ Cloud Pak for Data ’”.


Modificando o esquema em watsonx.data
: A seção Evolução do esquema do arquivo python de amostra permite modificar dados em watsonx.data


Atividades de manutenção de tabela em watsonx.data
: a manutenção de tabela ajuda a manter o desempenho da tabela watsonx.data O Iceberg oferece procedimentos de manutenção de tabelas prontos para uso, que permitem realizar otimizações avançadas de tabelas de forma declarativa. A amostra a seguir demonstra como executar algumas operações de manutenção de tabela usando o Spark

Para obter mais informações sobre as operações de manutenção de tabelas do Iceberg Spark, consulte Operações com tabelas.

Executando o caso de uso de amostra

Para executar casos de uso do Spark para watsonx.data usando arquivos Python de amostra:

  1. Salve a amostra a seguir como um arquivo Python :

    from pyspark.sql import SparkSession
    import os
    
    def init_spark():
        spark = SparkSession.builder \
            .appName("lh-hms-cloud") \
            .config("spark.hadoop.fs.s3a.bucket.lakehouse-bucket.endpoint" ,"<cos_bucket_endpoint>") \
            .config("spark.hadoop.fs.s3a.bucket.lakehouse-bucket.access.key" ,"<access_key>") \
            .config("spark.hadoop.fs.s3a.bucket.lakehouse-bucket.secret.key" ,"<secret_key>") \
            .enableHiveSupport() \
            .getOrCreate()
        return spark
    
    def create_database(spark):
        # Create a database in the lakehouse catalog
        spark.sql("create database if not exists lakehouse.demodb LOCATION 's3a://lakehouse-bucket/'")
    
    def list_databases(spark):
        # list the database under lakehouse catalog
        spark.sql("show databases from lakehouse").show()
    
    def basic_iceberg_table_operations(spark):
        # demonstration: Create a basic Iceberg table, insert some data and then query table
        spark.sql("create table if not exists lakehouse.demodb.testTable(id INTEGER, name VARCHAR(10), age INTEGER, salary DECIMAL(10, 2)) using iceberg").show()
        spark.sql("insert into lakehouse.demodb.testTable values(1,'Alan',23,3400.00),(2,'Ben',30,5500.00),(3,'Chen',35,6500.00)")
        spark.sql("select * from lakehouse.demodb.testTable").show()
    
    def create_table_from_parquet_data(spark):
        # load parquet data into dataframce
        df = spark.read.option("header",True).parquet("file:///spark-vol/yellow_tripdata_2022-01.parquet")
        # write the dataframe into an Iceberg table
        df.writeTo("lakehouse.demodb.yellow_taxi_2022").create()
        # describe the table created
        spark.sql('describe table lakehouse.demodb.yellow_taxi_2022').show(25)
        # query the table
        spark.sql('select * from lakehouse.demodb.yellow_taxi_2022').count()
    
    def ingest_from_csv_temp_table(spark):
        # load csv data into a dataframe
        csvDF = spark.read.option("header",True).csv("file:///spark-vol/zipcodes.csv")
        csvDF.createOrReplaceTempView("tempCSVTable")
        # load temporary table into an Iceberg table
        spark.sql('create or replace table lakehouse.demodb.zipcodes using iceberg as select * from tempCSVTable')
        # describe the table created
        spark.sql('describe table lakehouse.demodb.zipcodes').show(25)
        # query the table
        spark.sql('select * from lakehouse.demodb.zipcodes').show()
    
    def ingest_monthly_data(spark):
        df_feb = spark.read.option("header",True).parquet("file:///spark-vol/yellow_tripdata_2022-02.parquet")
        df_march = spark.read.option("header",True).parquet("file:///spark-vol/yellow_tripdata_2022-03.parquet")
        df_april = spark.read.option("header",True).parquet("file:///spark-vol/yellow_tripdata_2022-04.parquet")
        df_may = spark.read.option("header",True).parquet("file:///spark-vol/yellow_tripdata_2022-05.parquet")
        df_june = spark.read.option("header",True).parquet("file:///spark-vol/yellow_tripdata_2022-06.parquet")
        df_q1_q2 = df_feb.union(df_march).union(df_april).union(df_may).union(df_june)
        df_q1_q2.write.insertInto("lakehouse.demodb.yellow_taxi_2022")
    
    def perform_table_maintenance_operations(spark):
        # Query the metadata files table to list underlying data files
        spark.sql("SELECT file_path, file_size_in_bytes FROM lakehouse.demodb.yellow_taxi_2022.files").show()
        # There are many smaller files compact them into files of 200MB each using the
        # `rewrite_data_files` Iceberg Spark procedure
        spark.sql(f"CALL lakehouse.system.rewrite_data_files(table => 'demodb.yellow_taxi_2022', options => map('target-file-size-bytes','209715200'))").show()
        # Again, query the metadata files table to list underlying data files; 6 files are compacted
        # to 3 files
        spark.sql("SELECT file_path, file_size_in_bytes FROM lakehouse.demodb.yellow_taxi_2022.files").show()
        # List all the snapshots
        # Expire earlier snapshots. Only latest one with comacted data is required
        # Again, List all the snapshots to see only 1 left
        spark.sql("SELECT committed_at, snapshot_id, operation FROM lakehouse.demodb.yellow_taxi_2022.snapshots").show()
        #retain only the latest one
        latest_snapshot_committed_at = spark.sql("SELECT committed_at, snapshot_id, operation FROM lakehouse.demodb.yellow_taxi_2022.snapshots").tail(1)[0].committed_at
        print (latest_snapshot_committed_at)
        spark.sql(f"CALL lakehouse.system.expire_snapshots(table => 'demodb.yellow_taxi_2022',older_than => TIMESTAMP '{latest_snapshot_committed_at}',retain_last => 1)").show()
        spark.sql("SELECT committed_at, snapshot_id, operation FROM lakehouse.demodb.yellow_taxi_2022.snapshots").show()
        # Removing Orphan data files
        spark.sql(f"CALL lakehouse.system.remove_orphan_files(table => 'demodb.yellow_taxi_2022')").show(truncate=False)
        # Rewriting Manifest Files
        spark.sql(f"CALL lakehouse.system.rewrite_manifests('demodb.yellow_taxi_2022')").show()
    
    def evolve_schema(spark):
        # demonstration: Schema evolution
        # Add column fare_per_mile to the table
        spark.sql('ALTER TABLE lakehouse.demodb.yellow_taxi_2022 ADD COLUMN(fare_per_mile double)')
        # describe the table
        spark.sql('describe table lakehouse.demodb.yellow_taxi_2022').show(25)
    
    def clean_database(spark):
        # clean-up the demo database
        spark.sql('drop table if exists lakehouse.demodb.testTable purge')
        spark.sql('drop table if exists lakehouse.demodb.zipcodes purge')
        spark.sql('drop table if exists lakehouse.demodb.yellow_taxi_2022 purge')
        spark.sql('drop database if exists lakehouse.demodb cascade')
    
    def main():
        try:
            spark = init_spark()
            create_database(spark)
            list_databases(spark)
            basic_iceberg_table_operations(spark)
            # demonstration: Ingest parquet and csv data into a wastonx.data Iceberg table
            create_table_from_parquet_data(spark)
            ingest_from_csv_temp_table(spark)
            # load data for the month of Feburary to June into the table yellow_taxi_2022 created above
            ingest_monthly_data(spark)
            # demonstration: Table maintenance
            perform_table_maintenance_operations(spark)
            # demonstration: Schema evolution
            evolve_schema(spark)
        finally:
            # clean-up the demo database
            clean_database(spark)
            spark.stop()
    
    if __name__ == '__main__':
      main()
    
  2. Faça upload do arquivo Python no cpd-volume.

  3. Gere um token de acesso Consulte Gerando um token de autorização da API.

  4. Execute o seguinte comando curl para enviar o aplicativo Spark. Para obter mais informações sobre o envio de um aplicativo Spark, consulte Sintaxe da API de tarefas do Spark, parâmetros e códigos de retorno

    curl -k -X POST https://<cpd-url>/v4/analytics_engines/<intstnce id>/spark_applications -H "Authorization: ZenApiKey ${TOKEN}" -X POST -d '{
        "application_details": {
            "application": "/spark-vol/<pythonfile-name>.py",
            "conf": {
                "spark.driver.extraClassPath": "/opt/ibm/connectors/iceberg-lakehouse/iceberg-3.3.2-1.2.1-hms-4.0.0-shaded.jar"
            }
        },
        "volumes": [{
            "name": "cpd-instance::<volume-name>",
            "mount_path": "/spark-vol/",
            "source_sub_path": "spark"
        }]
    }'
    

    Exemplo:

    curl -k -X POST https://cpd-cpd-instance.apps.spark-cpd-test.cp.fyre.ibm.com/v4/analytics_engines/14c3c133-ba87-406c-a06d-16157d969d5b/spark_applications -H "Authorization: ZenApiKey eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IllZR1FJWkpoX3dYSWRrTXNqMV95dU5qR3VUeW1LT0xYcU1UN1UxSmxFUk0ifQ.eyJ1c2VybmFtZSI6ImFkbWluIiwicm9sZSI6IkFkbWluIiwicGVybWlzc2lvbnMiOlsiYWRtaW5pc3RyYXRvciIsImNhbl9wcm92aXNpb24iLCJtb25pdG9yX3BsYXRmb3JtIiwiY29uZmlndXJlX3BsYXRmb3JtIiwidmlld19wbGF0Zm9ybV9oZWFsdGgiLCJjb25maWd1cmVfYXV0aCIsIm1hbmFnZV91c2VycyIsIm1hbmFnZV9ncm91cHMiLCJtYW5hZ2Vfc2VydmljZV9pbnN0YW5jZXMiXSwiZ3JvdXBzIjpbMTAwMDBdLCJzdWIiOiJhZG1pbiIsImlzcyI6IktOT1hTU08iLCJhdWQiOiJEU1giLCJ1aWQiOiIxMDAwMzMwOTk5IiwiYXV0aGVudGljYXRvciI6ImRlZmF1bHQiLCJkaXNwbGF5X25hbWUiOiJhZG1pbiIsImFwaV9yZXF1ZXN0IjpmYWxzZSwiaWF0IjoxNjkwOTcyNDgwLCJleHAiOjE2OTEwMTU2ODB9.ALFvnY7cYNENfMpPRncxcKXCkt4F_xy8sI50DoQgtu_oSFB9fbstrUMe8XbNwermM-DCpC64XGjJdZaYeHXumCaelPETeQdqQnYRWONvyr18-y5Xn4GZlSvzzmiRvhzGZ-bt5cLsC_iEftouS_Opm_wnfaMUjYIPjVEzjFBTQh6PDMo7Q79kdZIyeZbHCKdKYVUpaZgHWKvZqMtNGGnm9PydN5TIRMws81817l96a7LWkI4UZYgybX53iNU0Mun_4iYqEizQm_dmII0_I7YkA1bBQuVtKcRFqfG5MucAR0REz3k9sBIXzn_qTFFrN_lQr2oSnWHviLUyAy1UCaHQNw" -X POST -d '{
        "application_details": {
            "application": "/spark-vol/test-cpdspark.py",
            "conf": {
                "spark.driver.extraClassPath": "/opt/ibm/connectors/iceberg-lakehouse/iceberg-3.3.2-1.2.1-hms-4.0.0-shaded.jar",
    
            }
        },
        "volumes": [{
            "name": "cpd-instance::spark-artifacts-vol",
            "mount_path": "/spark-vol/",
            "source_sub_path": "spark"
        }]
    }'
    

Inserindo dados de amostra no volume do Cloud Pak for Data

Para inserir dados no volume do Cloud Pak for Data :

  1. Crie um volume, denominado spark-vol, para armazenar dados de amostra a serem alimentados para a instância watsonx.data Para obter informações sobre como criar um volume, consulte Gerenciando volumes de armazenamento.

  2. Baixe os seguintes dados de exemplo do Parquet e o arquivo de exemplo do ` CSV `:

  3. Faça upload dos dados de amostra no volume spark-vol . Para obter instruções, consulte Navegar pelo volume de armazenamento e fazer upload do conteúdo