Cómo recortar a la mitad el tiempo de un pipeline de AWS Glue
Cuatro cambios de mecanismo, sin tocar la lógica de negocio, bajan un 56% el runtime de una cadena de ingesta, empaquetado y cifrado en Glue y PySpark.

Un pipeline de producción en AWS Glue y PySpark ha pasado de tardar lo que tardaba a la mitad. El autor de la optimización cifra el recorte en un 56% de extremo a extremo. La cadena hace ingesta de Oracle a S3, empaqueta, cifra y transfiere a una plataforma analítica; nada de la lógica de negocio se tocó. El trabajo se dividió en cuatro frentes, y otros dos intentos se quedaron en diagnóstico.
Concurrencia, bytes y el driver
La ingesta de 63 tablas corría por un Map de Step Functions con concurrencia 30. Con 63 elementos eso obliga a tres oleadas, y el reloj lo marca el último ítem en terminar, no el más lento. La ejecución se quedaba en 13:55. Subir la concurrencia a 50 la dejó en dos oleadas y unos 8 minutos. El autor insiste en que las oleadas son un acantilado: el beneficio está en cruzar el umbral, no en afinar el número. Empaquetar primero las tablas grandes ayuda, para que ninguna quede atrapada en la última oleada.
En la capa de publicación se reescribían los mismos bytes tres veces: un pase de renombrado, otro de saltos de línea y otro de estandarización, cada uno releyendo el conjunto completo. Escribir los bytes finales una sola vez, directos desde los executors, y paralelizar la reconciliación llevó esa fase de unos 25 minutos a 7.
El trabajo de salida comprime, cifra con GPG y sube con SSE-KMS. Corría en Glue Spark con 6 DPU en G.2X y era lento por un motivo tonto: todo iba en serie en el driver, con Spark usado solo para construir un DataFrame de log al final. La compresión es la fase limitada por CPU, así que el autor la pasó a hilos y bajó DEFLATE a nivel 1. De 9 minutos a 4. Los ZIP salen algo más grandes; era un intercambio asumible porque el cuello era el tiempo, no el tamaño. Con GPG había dos trampas: comprime antes de cifrar por defecto, y sobre datos ya comprimidos gastaba CPU y el resultado incluso crecía (un lote pasó de 5246 MB a 5312 MB); --compress-algo none lo arregla. Paralelizar el cifrado mató el driver por OOM, así que quedó en serie. La solución de verdad, aplicada aparte, es cifrar fichero a fichero con gpg.encrypt_file, con su propio GNUPGHOME, y escribir binario sin armar.
Cuando Spark es la herramienta equivocada
Otro trabajo movía ficheros grandes a un endpoint SFTP externo desde Glue Spark y no hacía nada distribuido. Estaba limitado por ancho de banda a unos 11 MB/s con ficheros de unos 5 GB, y subir la concurrencia del conector no cambiaba nada. Pasarlo a un job de Glue Python Shell con 1 DPU mantuvo el caudal y bajó el coste anual de unos 63 dólares a 11, a 0,44 dólares por DPU-hora.
Las dos investigaciones que no llegaron a victoria: una partición JDBC que hacía un full scan por conexión (8,9M filas en 8 minutos, pero 25M en producción tardaban 2h45m y subiendo; el problema era una columna particionada calculada que Oracle no puede indexar) y un cuelgue de 2h42m que desapareció al relanzar, causado por una lectura de socket JDBC sin timeout.
El patrón que se repite: los cuatro recortes vinieron de mecanismos, no de lógica. Cruzar un límite de concurrencia, dejar de tocar los mismos bytes dos veces, paralelizar la fase que encaja con el recurso disponible y ajustar el runtime al trabajo real. En dos de los casos el diagnóstico apuntaba a skew y a un cuelgue aleatorio, y una sola consulta tumbó la primera teoría. Antes de tocar nada conviene probar dónde está el cuello de verdad; la mitad de la historia vive en la base de datos origen, donde el Spark UI no llega.

