Note:

Migración de scripts de Apache Impala a Trino en Oracle Big Data Service

Introducción

Oracle Big Data Service (BDS) es un servicio basado en la nube proporcionado por Oracle que permite a los usuarios crear y gestionar clusters de Hadoop, clusters de Spark, Trino y otros servicios de big data. En el mundo del análisis de big data, Trino se destaca como un motor de consultas SQL distribuidas de alto rendimiento diseñado para ejecutar consultas analíticas interactivas en grandes conjuntos de datos. Trino permite consultar datos en varios orígenes, incluido Hadoop Distributed File System (HDFS), el cubo de OCI y las bases de datos relacionales tradicionales, todo ello dentro de una interfaz SQL unificada. Su capacidad para manejar datos a gran escala con baja latencia lo convierte en una herramienta poderosa para ingenieros de datos y analistas por igual.

Con el cambio a plataformas de datos modernas, muchas organizaciones están migrando de Apache Impala a Trino en Oracle Big Data Service. Este tutorial proporciona un enfoque paso a paso para automatizar y ajustar manualmente los scripts de Apache Impala para una migración perfecta a Trino.

Objetivos

Requisitos

Tarea 1: Automatización de la conversión de scripts

El script automatizado está diseñado para simplificar el proceso de conversión de scripts de Apache Impala para que sean compatibles con Trino en Oracle Big Data Service. Este script automatiza varias transformaciones clave, reduciendo la cantidad de esfuerzo manual necesario y minimizando la posibilidad de errores humanos durante el proceso de migración. Aquí hay un desglose de su funcionalidad.

  1. Procesamiento e inicialización de archivos.

    • El script comienza leyendo un archivo .hql de entrada (que normalmente se utiliza para las consultas de Apache Impala).

    • Crea un nuevo archivo de salida donde se guardará la consulta compatible con Trino convertida.

    • El script comienza agregando una línea para definir el contexto de catálogo y base de datos, utilizando USE catalog_name.schema_name, asegurando que las consultas se ejecuten en el contexto correcto en Trino.

  2. Transformaciones de consultas automatizadas.

    • Sobrescribir el manejo de tablas: el script busca cualquier sentencia OVERWRITE TABLE en el script de Apache Impala e inserta las sentencias DELETE FROM correspondientes justo encima de ellas. Esto garantiza que la tabla se borre antes de insertar nuevos datos, alineándose con la forma en que Trino maneja las sobrescrituras de datos.

    • Sustitución de funciones específicas de Impala: la secuencia de comandos aplica varias transformaciones para sustituir la sintaxis y funciones específicas de Apache Impala por funciones compatibles con Trino. Por ejemplo:

      • Se comentan los comandos invalidate metadata y REFRESH, ya que no son necesarios en Trino.

      • Los cambios de tipo de dato, como string a varchar, se realizan para que coincidan con los tipos de dato de Trino.

      • Las sentencias TRUNCATE TABLE de Impala se sustituyen por DELETE FROM, ya que Trino maneja el truncamiento de forma diferente.

      • COMPUTE STATS se sustituye por ANALYZE, lo que refleja cómo Trino recopila estadísticas.

      • Otras transformaciones específicas incluyen el manejo de funciones como nvl, ifnull y from_utc_timestamp, ajustándolas a la sintaxis y funciones de Trino.

      • Convirtiendo funciones nvl2 en expresiones COALESCE equivalentes.

      • Modificación de la coincidencia de expresiones regulares (REGEXP) con REGEXP_LIKE de Trino.

      • Ajustar las funciones de fecha y hora para alinearlas con la sintaxis de Trino.

    Script:

    #!/bin/bash
    # Function to apply transformations to an HQL file
    process_file() {
       local input_file="$1"
       local output_file="${input_file%.hql}_modified.hql"
       local diff_file="${input_file%.hql}_diff.sql"
    
       # Create the output file with the initial modification
       {
          echo "use catalog_name.schema_name;"
          cat "$input_file"
       } > "$output_file"
    
       # Insert DELETE FROM statements above OVERWRITE TABLE statements
       awk '
       BEGIN { IGNORECASE = 1 }
       {
          if (match($0, /OVERWRITE[[:space:]]+TABLE[[:space:]]+([^[:space:]]+)/, arr)) {
                print "DELETE FROM " arr[1] ";"
          }
          else if (match($0, /OVERWRITE[[:space:]]+([^[:space:]]+)/, arr)) {
          print "DELETE FROM " arr[1] ";"
          }
          print
       }' "$output_file" > temp_file && mv temp_file "$output_file"
    
       # Define replacements as array of tuples (search, replace)
       declare -a replacements=(
          "old_line1 new_line1"
          "old_line2 new_line2"
          # Add more replacements as needed
       )
    
       # Apply replacements
       for replacement in "${replacements[@]}"; do
          search_text=$(echo "$replacement" | awk '{print $1}')
          replace_text=$(echo "$replacement" | awk '{print $2}')
          sed -i "s/${search_text}/${replace_text}/Ig" "$output_file"
       done
    
       # Handle specific replacements
       sed -i 's/invalidate metadata/--invalidate metadata/Ig' "$output_file"
       sed -i 's/REFRESH/--REFRESH/Ig' "$output_file"
       sed -i 's/ string/ varchar/Ig' "$output_file"
       sed -i 's/TRUNCATE[[:space:]]\+TABLE[[:space:]]*/DELETE FROM /Ig' "$output_file"
       sed -i 's/TRUNCATE /DELETE FROM /Ig' "$output_file"
       sed -i 's/OVERWRITE[[:space:]]\+TABLE[[:space:]]*/INTO /Ig' "$output_file"
       sed -i 's/COMPUTE[[:space:]]\+stats/ANALYZE/Ig' "$output_file"
       sed -i 's/INSERT[[:space:]]\+INTO[[:space:]]\+TABLE/INSERT INTO/Ig' "$output_file"
       sed -i 's/from_utc_timestamp(now(),/current_timestamp AT TIME ZONE /Ig' "$output_file"
       sed -i "s/'America\/New_York')/'America\/New_York'/Ig" "$output_file"
       sed -i 's|/\* +NOSHUFFLE \*/| |Ig' "$output_file"
       sed -i 's/into[[:space:]]\+table/into/Ig' "$output_file"
       sed -i 's/STRAIGHT_JOIN/ /Ig' "$output_file"
       sed -i 's/OVERWRITE[[:space:]]\+/INTO /Ig' "$output_file"
       sed -i 's/TABLE[[:space:]]\+INTO/INTO/Ig' "$output_file"
       sed -i 's/SET[[:space:]]\+DECIMAL_V2/--SET DECIMAL_V2/Ig' "$output_file"
       sed -i 's/nvl(/COALESCE(/Ig' "$output_file"
       sed -i 's/ifnull(/COALESCE(/Ig' "$output_file"
       sed -i 's/CREATE[[:space:]]\+EXTERNAL/CREATE/Ig' "$output_file"
       sed -i -E 's/TRUNC[[:space:]]*\(/TRUNCATE(/Ig' "$output_file"
       sed -i -E 's/CAST[[:space:]]*\(/TRY_CAST(/Ig' "$output_file"
       sed -i -E 's/instr[[:space:]]*\(/strpos(/Ig' "$output_file"
       sed -i 's/""[[:space:]]\+as/null as/Ig' "$output_file"
       sed -i -E 's/\$\{var\:([^}]*)\}/\$\{\1\}/Ig' "$output_file"
       sed -i -E 's/([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]+REGEXP[[:space:]]+('\''[^'\'']*'\'')/REGEXP_LIKE(\1, \2)/Ig' "$output_file"
       sed -i -E 's/lower\(([a-zA-Z_][a-zA-Z0-9_]*\))[[:space:]]+REGEXP[[:space:]]+('\''[^'\'']*'\'')/REGEXP_LIKE(lower(\1, \2)/Ig' "$output_file"
       sed -i "s/)\s*STORED\s*AS\s*PARQUET\s*LOCATION\s*'\([^']*\)';/) WITH (\nexternal_location = '\1',\nformat = 'PARQUET'\n);/Ig" "$output_file"    
       sed -i -E "s/try_cast\(extract\(([a-zA-Z0-9_.]+), 'MONTH'\) AS varchar\)/try_cast(extract(MONTH from try_cast(\1 AS timestamp)) as VARCHAR)/Ig" "$output_file"
       sed -i -E "s/TRY_CAST\(extract\(add_months\(([^,]+),([^,]+)\),[[:space:]]*'MONTH'\)[[:space:]]*AS[[:space:]]*varchar\)/TRY_CAST\(extract\(MONTH from date_add\('month',\2,try_cast\(\1 as timestamp\)\)\) AS varchar\)/Ig" "$output_file"
       sed -Ei "s/try_cast\(ADD_MONTHS\(([^,]+),\s*-?\s*([0-9]+)\) AS varchar\)/try_cast\(date_add\('month', -\2, try_cast(\1 as timestamp)\) AS varchar\)/Ig" "$output_file"
       sed -i -E 's/DATEDIFF\(/date_diff\('\''day'\'', /Ig' "$output_file"
       sed -i -E 's/TO_DATE\(/DATE\(/Ig' "$output_file"
       sed -i -E 's/now\(\)/current_timestamp/Ig' "$output_file"
    
       # Generate the diff file
       diff -u "$input_file" "$output_file" > "$diff_file"
    
       echo "Processed $input_file -> $output_file. Diff file created: $diff_file"
    }
    
    # Check arguments
    if [ "$#" -ne 1 ]; then
       echo "Usage: $0 <file_or_directory>"
       exit 1
    fi
    
    TARGET="$1"
    
    # Check if the target is a directory
    if [ -d "$TARGET" ]; then
       for file in "$TARGET"/*.hql; do
          [ -e "$file" ] || continue # Skip if no HQL files found
          process_file "$file"
       done
    elif [ -f "$TARGET" ]; then
       process_file "$TARGET"
    else
       echo "Invalid input: $TARGET is neither a file nor a directory."
       exit 1
    fi
    

    Nota Este script proporciona un enfoque básico para convertir scripts de Apache Impala en Trino, pero no cubre todas las sentencias y escenarios posibles de Impala. Si encuentra sintaxis específica de Impala o funciones adicionales que no maneja este script, puede ampliar el script agregando nuevas reglas de transformación para cubrir esos casos. La actualización periódica del script con estas modificaciones mejorará su eficacia para futuras conversiones

Tarea 2: Ejecución del script de conversión

  1. Guarde el script en el nodo perimetral de Oracle Big Data Service.

  2. Ejecute el script con el archivo o directorio de destino que contiene los scripts de Apache Impala.

  3. Revise los archivos de salida y diferencia generados para los cambios.

Tarea 3: Realizar ajustes manuales

  1. Utilice la sentencia LEFT ANTI JOIN.

    Algunas construcciones SQL de Apache Impala, como LEFT ANTI JOIN, requieren intervención manual. Identifique las sentencias LEFT ANTI JOIN en el script Impala y sustitúyalas por Trino SQL equivalente mediante LEFT JOIN con una cláusula WHERE.

    Scripts de ejemplo:

    • Guión de Impala:

      SELECT t1.*
       FROM table1 t1
       LEFT ANTI JOIN table2 t2 ON t1.key = t2.key;
      
    • Guión de Trino:

      SELECT t1.*
       FROM table1 t1
       LEFT JOIN table2 t2 ON t1.key = t2.key
       WHERE t2.key IS NULL;
      
  2. Ajuste las cláusulas GROUP BY.

    Trino permite la agrupación basada en posiciones en la cláusula GROUP BY, lo que puede simplificar las agrupaciones largas. Convierta los nombres de columna en sus equivalentes posicionales en la cláusula GROUP BY cuando sea necesario. Asegúrese de que todas las columnas están asignadas correctamente.

    Scripts de ejemplo:

    • Guión de Impala:

      GROUP BY sales_data.region,
          sales_data.product_name,
          sales_data.transaction_id,
          transaction_date,
          last_updated,
          inventory.stock_quantity,
          sales_amount,
          discount_status,
          inventory_cost,
          total_revenue,
          revenue_status,
          reporting_period,
          report_generated_date;
      
    • Guión de Trino:

      GROUP BY sales_data.region,
          sales_data.product_name,
          sales_data.transaction_id,
          transaction_date,
          last_updated,
          inventory.stock_quantity,
          7,  -- sales_amount
          8,  -- discount_status
          9,  -- inventory_cost
          10, -- total_revenue
          11, -- revenue_status
          12, -- reporting_period
          13; -- report_generated_date
      

Solución de problemas y consejos

Pasos Siguientes

Después de completar la migración de scripts de Apache Impala a Trino en Oracle Big Data Service, es importante validar los scripts convertidos a fondo. Comience ejecutando los scripts de Trino convertidos en un entorno de prueba para asegurarse de que producen los resultados esperados. Preste mucha atención a las diferencias de rendimiento, especialmente en consultas complejas que implican uniones o agregaciones, ya que el motor de ejecución de Trino puede comportarse de manera diferente en comparación con Impala.

Además, considere la posibilidad de optimizar las nuevas consultas de Trino analizando los planes de consulta y realizando los ajustes necesarios. Por último, documente los desafíos específicos o las lecciones aprendidas durante el proceso de migración, ya que esto será valioso para futuras migraciones.

Agradecimientos

Más recursos de aprendizaje

Explore otros laboratorios en docs.oracle.com/learn o acceda a más contenido de formación gratuita en el canal YouTube de Oracle Learning. Además, visita education.oracle.com/learning-explorer para convertirte en un Oracle Learning Explorer.

Para obtener documentación sobre el producto, visite Oracle Help Center.