Tema
📒 Clase 5 — Data lake: SQL sobre archivos con Athena
Curso AWS (emulador Floci) · 2026-08-08 · Carpeta:
02-Ejercicios/clase-05-athena⬅️ Volver al índice de clases
🎯 Qué aprendí
- Qué es un data lake y por qué consultar archivos cambia la economía del análisis.
- Que el catálogo —no el archivo— es lo que convierte un CSV en una tabla.
- Ejecutar SQL contra S3 sin ninguna base de datos encendida.
- Que una consulta es asíncrona: se lanza, se espera y se recogen los resultados.
- Por qué en AWS se paga por datos leídos, y qué decisiones cambia eso.
- Tres límites del emulador, incluido uno que deja Athena inservible hasta reiniciar.
📖 PARTE TEÓRICA
🏞️ 1. Un lago no es una base de datos
En la Clase 2 pediste un servidor y le metiste datos. Aquí no hay servidor:
BASE DE DATOS (RDS) DATA LAKE (S3 + Athena)
─────────────────── ──────────────────────
┌─────────────┐ ┌─────────────┐
│ servidor │ encendido │ S3 │ solo archivos
│ siempre │ 24/7 │ (parados) │
└──────┬──────┘ └──────┬──────┘
│ │ al consultar:
importas los datos ┌──────▼──────┐
ANTES de consultar │ ATHENA │ arranca, lee,
│ (efimero) │ responde, se apaga
✓ milisegundos └─────────────┘
✓ transacciones ✓ cero coste en reposo
✗ pagas aunque nadie ✓ escala a terabytes
consulte ✗ segundos, no milisegundos💡 La regla para elegir: si una aplicación consulta cada pocos segundos, base de datos. Si alguien analiza de vez en cuando volúmenes grandes, data lake. Y nada impide tener ambos: es lo normal.
📇 2. El catálogo: lo que convierte un archivo en tabla
Un CSV en S3 es solo texto. Para que Athena lo entienda como tabla hace falta declarar su estructura en un catálogo (AWS Glue):
s3://mi-lago/atenciones/atenciones.csv ← el archivo, texto plano
▲
│ apunta a
┌───────┴────────┐
│ CATALOGO │ nombre: atenciones
│ (AWS Glue) │ columnas: especialidad text, atenciones int...
└────────────────┘ ubicacion: s3://mi-lago/atenciones/
│
▼
SELECT * FROM atencionesLo importante: el catálogo no copia los datos. Solo dice «en esa carpeta hay filas con estas columnas». Si mañana añades otro CSV a esa carpeta, las consultas lo incluyen sin tocar nada.
⚠️ La ubicación es una carpeta, no un archivo. Athena lee todo lo que haya dentro. Dejar ahí un archivo con otro formato rompe las consultas.
⏱️ 3. Una consulta es asíncrona
En PostgreSQL lanzas la consulta y esperas la respuesta en la misma llamada. En Athena son tres pasos:
start-query-execution ──▶ devuelve un ID, no resultados
│
▼
get-query-execution ──▶ QUEUED → RUNNING → SUCCEEDED | FAILED
│ (sondear hasta que termine)
▼
get-query-results ──▶ las filasTiene sentido: una consulta sobre terabytes puede tardar minutos, y nadie quiere una conexión abierta esperando.
💡 La primera fila de
get-query-resultsson los nombres de las columnas, no datos. Es un detalle que sorprende y que hay que recordar al procesar la respuesta.
💰 4. Se paga por datos leídos
Aquí está la diferencia económica que más decisiones cambia:
| RDS | Athena | |
|---|---|---|
| Se paga por | Hora encendida | Datos leídos por consulta |
| Consulta que no se hace | Cuesta igual | Cuesta cero |
SELECT * sobre todo | Igual de caro | Muy caro |
| Filtrar bien | Mejora velocidad | Mejora velocidad y factura |
Por eso en un data lake importan tanto el formato y la organización:
- Particionar por fecha (
año=2026/mes=07/) permite leer solo lo necesario. - Parquet en vez de CSV: columnar y comprimido, lee mucho menos para lo mismo.
- Seleccionar columnas en vez de
SELECT *: en Parquet, lee solo esas columnas.
🧪 Pregunta de entrevista: ¿por qué
SELECT *es peor en Athena que en PostgreSQL? Porque en Athena se factura por bytes escaneados: pedir columnas que no usas se paga.
🦆 5. Qué hay debajo en el emulador
Floci ejecuta el SQL con un contenedor DuckDB (floci-duck) que arranca en la primera consulta. Lee las tablas del catálogo y crea vistas apuntando a S3.
start-query-execution
│
▼
┌────────────┐ lee las tablas de Glue y genera
│ FLOCI │ CREATE OR REPLACE VIEW ... read_csv_auto('s3://...')
└─────┬──────┘
▼
┌────────────┐ ejecuta el SQL de verdad
│ floci-duck │ y guarda el resultado como CSV en S3
└────────────┘⚠️ 6. Tres límites del emulador
1 · CREATE EXTERNAL TABLE no registra nada. La DDL de Athena se queda en RUNNING sin crear la tabla. Hay que registrarla en Glue con create-table.
2 · El sidecar tiene 128 MiB y se queda sin memoria. Con un CSV de 349 bytes:
Out of Memory Error: could not allocate block of size 76.5 MiB (31.5 MiB/102.3 MiB used)3 · Y recuperarlo exige reiniciar Floci entero. Esto es lo que más tiempo cuesta descubrir: reiniciar el sidecar no basta, y eliminarlo lo empeora —Floci conserva su dirección antigua y responde No route to host—. La única salida es floci restart.
📝 Reiniciar Floci borra todo el estado en memoria: buckets, tablas, catálogo. Después hay que rehacer el lago. Conviene tener el montaje en un script, no en comandos sueltos.
💻 PARTE PRÁCTICA
bash
floci start
eval $(floci env)Montar el lago son tres pasos: el archivo, la base del catálogo y la tabla.
bash
# 1. el archivo
aws s3 mb s3://clase05-lago
aws s3 mb s3://clase05-resultados
cat > atenciones.csv <<'CSV'
especialidad,modalidad,atenciones,mes
Cardiologia,Teleconsulta,412,2026-06
Cardiologia,Teleconsulta,487,2026-07
Neurologia,Teleinterconsulta,203,2026-06
Neurologia,Teleinterconsulta,256,2026-07
Endocrinologia,Teleconsulta,318,2026-06
Endocrinologia,Teleconsulta,295,2026-07
Psiquiatria,Teleconsulta,174,2026-07
Dermatologia,Telemonitoreo,91,2026-07
CSV
aws s3 cp atenciones.csv s3://clase05-lago/atenciones/
# 2. la base del catalogo
aws glue create-database --database-input '{"Name":"analitica"}'
# 3. la tabla
aws glue create-table --database-name analitica --table-input '{
"Name":"atenciones",
"StorageDescriptor":{
"Columns":[
{"Name":"especialidad","Type":"string"},
{"Name":"modalidad","Type":"string"},
{"Name":"atenciones","Type":"int"},
{"Name":"mes","Type":"string"}],
"Location":"s3://clase05-lago/atenciones/",
"InputFormat":"org.apache.hadoop.mapred.TextInputFormat",
"SerdeInfo":{"SerializationLibrary":"org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe"}
}}'Y una función para no repetir los tres pasos de cada consulta:
bash
athena() {
local Q
Q=$(aws athena start-query-execution --query-string "$1" \
--query-execution-context Database=analitica \
--result-configuration OutputLocation=s3://clase05-resultados/ \
--query 'QueryExecutionId' --output text)
until [ "$(aws athena get-query-execution --query-execution-id "$Q" \
--query 'QueryExecution.Status.State' --output text)" != "RUNNING" ]; do sleep 1; done
aws athena get-query-results --query-execution-id "$Q" \
--query 'ResultSet.Rows[*].Data[*].VarCharValue' --output text
}$ athena "SELECT COUNT(*) AS n, SUM(atenciones) AS total FROM atenciones"
n total
8 2236🏋️ EJERCICIOS CON SOLUCIÓN
🟢 Nivel 1 — Montar el lago (1-8)
Ejercicio 1 — Crear los dos buckets
Crea uno para los datos y otro para los resultados.
💡 ¿Sabías que…? — por qué dos buckets
Athena escribe el resultado de cada consulta como CSV. Si van al mismo sitio que los datos, la siguiente consulta intentaría leer sus propios resultados como si fueran datos.
bash
# ejemplo de referencia
aws s3 mb s3://otro-lago
aws s3 mb s3://otro-resultadosVer solución
bash
aws s3 mb s3://clase05-lago
aws s3 mb s3://clase05-resultadosEjercicio 2 — Subir el archivo
Sube el CSV a una carpeta atenciones/ dentro del bucket de datos.
💡 ¿Sabías que…? — S3 no tiene carpetas de verdad
atenciones/atenciones.csv es el nombre completo del objeto. La barra es una convención que las herramientas muestran como carpeta, pero el catálogo la usa igual como ubicación.
bash
# ejemplo de referencia
aws s3 cp datos.csv s3://otro-lago/ventas/Ver solución
bash
aws s3 cp atenciones.csv s3://clase05-lago/atenciones/
aws s3 ls s3://clase05-lago/atenciones/Ejercicio 3 — Crear la base del catálogo
Crea una base llamada analitica en Glue.
💡 ¿Sabías que…? — la base del catálogo no contiene datos
Es solo una agrupación de definiciones. Puedes tener varias (crudo, procesado, analitica) apuntando a los mismos archivos con distintas vistas.
bash
# ejemplo de referencia
aws glue create-database --database-input '{"Name":"pruebas"}'Ver solución
bash
aws glue create-database --database-input '{"Name":"analitica"}'
aws glue get-databases --query 'DatabaseList[*].Name' --output textEjercicio 4 — Registrar la tabla
Declara la estructura del CSV como tabla atenciones.
💡 ¿Sabías que…? — el SerDe decide cómo se lee
LazySimpleSerDe es el lector de texto delimitado. Cambiarlo por el de Parquet o JSON es lo que permite consultar otros formatos con el mismo SQL.
bash
# ejemplo de referencia — dos columnas
aws glue create-table --database-name pruebas --table-input '{
"Name":"ventas",
"StorageDescriptor":{
"Columns":[{"Name":"producto","Type":"string"},{"Name":"total","Type":"int"}],
"Location":"s3://otro-lago/ventas/",
"InputFormat":"org.apache.hadoop.mapred.TextInputFormat",
"SerdeInfo":{"SerializationLibrary":"org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe"}}}'Ver solución
Ver el bloque completo en la Parte Práctica. Lo esencial: Columns, Location (la carpeta), InputFormat y SerdeInfo.
Ejercicio 5 — Comprobar el registro
Muestra las columnas que quedaron registradas.
💡 ¿Sabías que…? — el catálogo se puede inspeccionar
Ver qué cree el catálogo que hay es el primer paso cuando una consulta devuelve columnas raras o vacías.
bash
# ejemplo de referencia
aws glue get-table --database-name pruebas --name ventas \
--query 'Table.StorageDescriptor.Columns[*].Name' --output textVer solución
bash
aws glue get-table --database-name analitica --name atenciones \
--query 'Table.StorageDescriptor.Columns[*].[Name,Type]' --output text
# especialidad string
# modalidad string
# atenciones int
# mes stringEjercicio 6 — Confirmar la ubicación
Averigua a qué carpeta de S3 apunta la tabla.
💡 ¿Sabías que…? — el error más común es apuntar mal
Si la ubicación apunta al archivo en vez de a la carpeta, o a una carpeta vacía, las consultas devuelven cero filas sin ningún error.
bash
# ejemplo de referencia
aws glue get-table --database-name pruebas --name ventas \
--query 'Table.StorageDescriptor.Location' --output textVer solución
bash
aws glue get-table --database-name analitica --name atenciones \
--query 'Table.StorageDescriptor.Location' --output text
# s3://clase05-lago/atenciones/Ejercicio 7 — Listar las tablas del catálogo
Muestra qué tablas hay registradas en analitica.
💡 ¿Sabías que…? — el catálogo es compartido
Athena, Glue y otros servicios de análisis leen el mismo catálogo. Registrar una tabla una vez la hace consultable desde todos.
bash
# ejemplo de referencia
aws glue get-tables --database-name pruebas --query 'TableList[*].Name' --output textVer solución
bash
aws glue get-tables --database-name analitica --query 'TableList[*].Name' --output text
# atencionesEjercicio 8 — Ver el archivo tal cual
Descarga el CSV y compruébalo: es texto plano, sin nada especial.
💡 ¿Sabías que…? — no hay ninguna magia en el archivo
El archivo no se transforma ni se indexa al registrarlo. Sigue siendo el mismo CSV que subiste; toda la inteligencia está en el catálogo y en el motor.
bash
# ejemplo de referencia
aws s3 cp s3://otro-lago/ventas/datos.csv -Ver solución
bash
aws s3 cp s3://clase05-lago/atenciones/atenciones.csv - | head -3
# especialidad,modalidad,atenciones,mes
# Cardiologia,Teleconsulta,412,2026-06🔵 Nivel 2 — Las primeras consultas (9-16)
Ejercicio 9 — Lanzar una consulta
Ejecuta SELECT COUNT(*) FROM atenciones y guarda el identificador.
💡 ¿Sabías que…? — no devuelve resultados
start-query-execution devuelve un identificador. Los resultados se recogen después, en otra llamada.
bash
# ejemplo de referencia
aws athena start-query-execution --query-string "SELECT 1" \
--query-execution-context Database=pruebas \
--result-configuration OutputLocation=s3://otro-resultados/ --query 'QueryExecutionId'Ver solución
bash
Q=$(aws athena start-query-execution \
--query-string "SELECT COUNT(*) FROM atenciones" \
--query-execution-context Database=analitica \
--result-configuration OutputLocation=s3://clase05-resultados/ \
--query 'QueryExecutionId' --output text)
echo "$Q"Ejercicio 10 — Consultar su estado
Averigua si terminó.
💡 ¿Sabías que…? — los cuatro estados
QUEUED, RUNNING, SUCCEEDED, FAILED. Solo con SUCCEEDED hay resultados que recoger.
bash
# ejemplo de referencia
aws athena get-query-execution --query-execution-id $Q \
--query 'QueryExecution.Status.State' --output textVer solución
bash
aws athena get-query-execution --query-execution-id "$Q" \
--query 'QueryExecution.Status.State' --output text
# SUCCEEDEDEjercicio 11 — Recoger los resultados
Muestra las filas.
💡 ¿Sabías que…? — la primera fila son las cabeceras
ResultSet.Rows[0] contiene los nombres de las columnas, no datos. Al procesarlo en código, hay que saltarla.
bash
# ejemplo de referencia — saltando la cabecera
aws athena get-query-results --query-execution-id $Q \
--query 'ResultSet.Rows[1:].Data[*].VarCharValue' --output textVer solución
bash
aws athena get-query-results --query-execution-id "$Q" \
--query 'ResultSet.Rows[*].Data[*].VarCharValue' --output text
# _col0
# 8Ejercicio 12 — Automatizar los tres pasos
Escribe una función de shell que lance, espere y devuelva resultados.
💡 ¿Sabías que…? — sondear hasta que deje de correr
Un bucle until sobre el estado es más robusto que un sleep fijo: funciona igual con consultas de un segundo y de un minuto.
bash
# ejemplo de referencia
until [ "$(estado)" != "RUNNING" ]; do sleep 1; doneVer solución
Ver la función athena() completa en la Parte Práctica.
Ejercicio 13 — Filtrar filas
Muestra solo las atenciones de julio.
💡 ¿Sabías que…? — filtrar es lo primero que abarata
En Athena, el filtro no solo acelera: reduce los bytes leídos, que es lo que se factura.
sql
-- ejemplo de referencia
SELECT * FROM ventas WHERE total > 100;Ver solución
bash
athena "SELECT especialidad, atenciones FROM atenciones WHERE mes = '2026-07'"Ejercicio 14 — Ordenar y limitar
Muestra la especialidad con más atenciones en julio.
💡 ¿Sabías que…? — `LIMIT` no reduce lo leído
Para devolver el máximo hay que mirar todas las filas. LIMIT recorta la respuesta, no el escaneo: no abarata la consulta.
sql
-- ejemplo de referencia
SELECT producto FROM ventas ORDER BY total DESC LIMIT 3;Ver solución
bash
athena "SELECT especialidad, atenciones FROM atenciones
WHERE mes='2026-07' ORDER BY atenciones DESC LIMIT 1"
# Cardiologia 487Ejercicio 15 — Seleccionar solo dos columnas
Devuelve únicamente especialidad y mes.
💡 ¿Sabías que…? — con Parquet, esto sí abarata
En CSV hay que leer la línea entera igualmente. En un formato columnar como Parquet, pedir dos columnas lee solo esas dos: la diferencia en factura es enorme.
sql
-- ejemplo de referencia
SELECT producto FROM ventas;Ver solución
bash
athena "SELECT especialidad, mes FROM atenciones LIMIT 3"Ejercicio 16 — Contar valores distintos
Averigua cuántas especialidades distintas hay.
💡 ¿Sabías que…? — `DISTINCT` obliga a comparar todo
Para saber cuántos valores únicos hay, el motor debe verlos todos y recordarlos. Es más caro que un COUNT(*) simple.
sql
-- ejemplo de referencia
SELECT COUNT(DISTINCT producto) FROM ventas;Ver solución
bash
athena "SELECT COUNT(DISTINCT especialidad) FROM atenciones"
# 5🟡 Nivel 3 — Analítica de verdad (17-26)
Ejercicio 17 — Total por especialidad
Suma las atenciones agrupando por especialidad, de mayor a menor.
💡 ¿Sabías que…? — el SQL es el mismo que en RDS
Lo que cambia es dónde viven los datos y cómo se factura. El lenguaje no.
sql
-- ejemplo de referencia
SELECT producto, SUM(total) t FROM ventas GROUP BY producto ORDER BY t DESC;Ver solución
bash
athena "SELECT especialidad, SUM(atenciones) AS total FROM atenciones
GROUP BY especialidad ORDER BY total DESC"
# Cardiologia 899Ejercicio 18 — Filtrar sobre el total
Muestra solo las especialidades que superen 400 atenciones.
💡 ¿Sabías que…? — `HAVING` va después de agrupar
Es la misma regla que en cualquier SQL: WHERE filtra filas, HAVING filtra grupos.
sql
-- ejemplo de referencia
SELECT producto FROM ventas GROUP BY producto HAVING SUM(total) > 500;Ver solución
bash
athena "SELECT especialidad FROM atenciones
GROUP BY especialidad HAVING SUM(atenciones) > 400"
# Cardiologia
# EndocrinologiaEjercicio 19 — Promedio por modalidad
Calcula la media de atenciones por modalidad, con un decimal.
💡 ¿Sabías que…? — `ROUND` mejora la lectura
Sin redondear, una media sale con quince decimales. En un informe, eso es ruido.
sql
-- ejemplo de referencia
SELECT ROUND(AVG(total), 2) FROM ventas;Ver solución
bash
athena "SELECT modalidad, ROUND(AVG(atenciones),1) AS promedio
FROM atenciones GROUP BY modalidad"
# Teleconsulta 337.2Ejercicio 20 — Mínimo y máximo
Muestra la atención más baja y la más alta del conjunto.
💡 ¿Sabías que…? — varios agregados en una pasada
Pedir MIN y MAX juntos recorre los datos una sola vez. Dos consultas separadas los recorrerían dos veces — y se pagarían dos veces.
sql
-- ejemplo de referencia
SELECT MIN(total), MAX(total), AVG(total) FROM ventas;Ver solución
bash
athena "SELECT MIN(atenciones) AS minimo, MAX(atenciones) AS maximo FROM atenciones"
# 91 487Ejercicio 21 — Clasificar con CASE
Etiqueta cada fila como alto si supera 300 atenciones, y bajo si no.
💡 ¿Sabías que…? — `CASE` crea columnas que no existen
Permite derivar categorías sin tocar los datos de origen. Es la forma de añadir criterio de negocio en la consulta.
sql
-- ejemplo de referencia
SELECT producto, CASE WHEN total > 100 THEN 'top' ELSE 'normal' END AS tipo FROM ventas;Ver solución
bash
athena "SELECT especialidad,
CASE WHEN atenciones > 300 THEN 'alto' ELSE 'bajo' END AS nivel
FROM atenciones LIMIT 3"
# Cardiologia altoEjercicio 22 — Buscar por patrón
Cuenta cuántas filas hay de especialidades que empiecen por Cardio.
💡 ¿Sabías que…? — `LIKE` con comodín al final es el más eficiente
'Cardio%' puede aprovecharse mejor que '%logia', que obliga a mirar toda la cadena.
sql
-- ejemplo de referencia
SELECT COUNT(*) FROM ventas WHERE producto LIKE 'Tele%';Ver solución
bash
athena "SELECT COUNT(*) FROM atenciones WHERE especialidad LIKE 'Cardio%'"
# 2Ejercicio 23 — Una consulta por pasos (CTE)
Calcula el total general usando una expresión con nombre.
💡 ¿Sabías que…? — las CTE también funcionan aquí
Athena admite SQL moderno completo. Una consulta compleja se puede escribir en pasos legibles en vez de anidar subconsultas.
sql
-- ejemplo de referencia
WITH top AS (SELECT * FROM ventas WHERE total > 100) SELECT COUNT(*) FROM top;Ver solución
bash
athena "WITH t AS (SELECT SUM(atenciones) AS s FROM atenciones) SELECT s FROM t"
# 2236Ejercicio 24 — Ranking con función de ventana
Añade el puesto de cada fila según sus atenciones.
💡 ¿Sabías que…? — las ventanas conservan las filas
Igual que en PostgreSQL: calculan sobre el conjunto sin colapsarlo. Aquí también funcionan.
sql
-- ejemplo de referencia
SELECT producto, ROW_NUMBER() OVER (ORDER BY total DESC) FROM ventas;Ver solución
bash
athena "SELECT especialidad, RANK() OVER (ORDER BY atenciones DESC) AS puesto
FROM atenciones LIMIT 3"
# Cardiologia 1Ejercicio 25 — Cruzar la tabla consigo misma
Une las filas por mes para comparar especialidades del mismo periodo.
💡 ¿Sabías que…? — los JOIN son caros en un lago
Cruzar obliga a leer y comparar ambos lados. En volúmenes grandes es la operación que más factura. Por eso los datos de un lago suelen estar desnormalizados.
sql
-- ejemplo de referencia
SELECT a.producto FROM ventas a JOIN ventas b ON a.mes = b.mes LIMIT 1;Ver solución
bash
athena "SELECT a.especialidad, b.especialidad
FROM atenciones a JOIN atenciones b ON a.mes = b.mes LIMIT 3"Ejercicio 26 — Subconsulta
Muestra la especialidad con el valor máximo, sin ordenar.
💡 ¿Sabías que…? — subconsulta frente a ORDER BY + LIMIT
Ambas resuelven lo mismo. La subconsulta es más explícita y devuelve todos los empates; ORDER BY … LIMIT 1 devuelve solo uno.
sql
-- ejemplo de referencia
SELECT producto FROM ventas WHERE total = (SELECT MAX(total) FROM ventas);Ver solución
bash
athena "SELECT especialidad FROM atenciones
WHERE atenciones = (SELECT MAX(atenciones) FROM atenciones)"
# Cardiologia🟠 Nivel 4 — Cómo funciona por dentro (27-34)
Ejercicio 27 — Encontrar el resultado en S3
Localiza el CSV que Athena dejó tras una consulta.
💡 ¿Sabías que…? — el resultado también es un archivo
Athena guarda cada resultado en el bucket de salida, con el identificador de la consulta como nombre. Se puede volver a descargar sin repetir la consulta.
bash
# ejemplo de referencia
aws s3 ls s3://otro-resultados/ --recursiveVer solución
bash
aws s3 ls s3://clase05-resultados/ --recursive | tail -3Ejercicio 28 — Descargar ese resultado
Recupera el contenido del CSV de resultados.
💡 ¿Sabías que…? — el resultado es reutilizable
Otra herramienta puede leer ese CSV sin pasar por Athena. Es como se encadenan procesos de análisis en un lago.
bash
# ejemplo de referencia
aws s3 cp s3://otro-resultados/abc123.csv -Ver solución
bash
CSV=$(aws s3 ls s3://clase05-resultados/ --recursive | tail -1 | awk '{print $4}')
aws s3 cp "s3://clase05-resultados/$CSV" -Ejercicio 29 — Ver cuánto tardó
Consulta las estadísticas de ejecución de una consulta.
💡 ¿Sabías que…? — el tiempo y los bytes leídos
Statistics incluye la duración y los datos escaneados. En AWS, esa segunda cifra es literalmente la factura de esa consulta.
bash
# ejemplo de referencia
aws athena get-query-execution --query-execution-id $Q --query 'QueryExecution.Statistics'Ver solución
bash
aws athena get-query-execution --query-execution-id "$Q" \
--query 'QueryExecution.Statistics' 2>/dev/nullEjercicio 30 — Añadir datos sin tocar el catálogo
Sube un segundo CSV a la misma carpeta y vuelve a consultar.
💡 ¿Sabías que…? — el catálogo apunta a la carpeta
Todo lo que caiga dentro entra en las consultas automáticamente. No hay que registrar nada nuevo — ni cargar, ni importar.
bash
# ejemplo de referencia
aws s3 cp mas-datos.csv s3://otro-lago/ventas/Ver solución
bash
printf 'Oftalmologia,Teleconsulta,150,2026-07\n' > extra.csv
aws s3 cp extra.csv s3://clase05-lago/atenciones/
athena "SELECT COUNT(*) FROM atenciones"
# 9 ← una mas, sin tocar el catalogo⚠️ El segundo archivo no debe llevar cabecera, o esa línea se leería como una fila de datos.
Ejercicio 31 — Comprobar qué archivos lee
Lista todo lo que hay en la carpeta que la tabla apunta.
💡 ¿Sabías que…? — un archivo intruso rompe las consultas
Si alguien deja ahí un .txt con otro formato, Athena intentará leerlo como datos y fallará o devolverá basura.
bash
# ejemplo de referencia
aws s3 ls s3://otro-lago/ventas/Ver solución
bash
aws s3 ls s3://clase05-lago/atenciones/
# atenciones.csv
# extra.csvEjercicio 32 — Comparar la velocidad con RDS
Ejecuta un agregado equivalente en Athena y en la base de la Clase 2, y compara los tiempos.
💡 ¿Sabías que…? — es la comparación que resume la clase
Athena arranca un motor al consultar; RDS ya está encendido. La diferencia no es un defecto: es el compromiso que eliges al escoger cada uno.
bash
# ejemplo de referencia
time athena "SELECT COUNT(*) FROM atenciones"Ver solución
bash
time athena "SELECT especialidad, SUM(atenciones) FROM atenciones GROUP BY especialidad"
# ~2 segundos
# la misma consulta en RDS (Clase 2): ~8 milisegundosUnas 250 veces más lento — y aun así, Athena es la elección correcta cuando los datos son enormes y las consultas, ocasionales.
Ejercicio 33 — Consultar una tabla vacía
Crea una tabla que apunte a una carpeta sin archivos y consúltala.
💡 ¿Sabías que…? — cero filas no es un error
Una ubicación equivocada no da error: devuelve cero filas. Es el fallo más difícil de detectar porque parece que los datos no existen.
bash
# ejemplo de referencia
aws glue create-table --database-name pruebas --table-input '{...Location: s3://vacio/...}'Ver solución
bash
aws s3 mb s3://clase05-vacio 2>/dev/null
# registrar una tabla apuntando a s3://clase05-vacio/ y consultarla
athena "SELECT COUNT(*) FROM tabla_vacia"
# 0 ← sin error, sin datosEjercicio 34 — Varias bases en el catálogo
Crea una segunda base y comprueba que las tablas no se mezclan.
💡 ¿Sabías que…? — separar por etapa del dato
Es habitual tener crudo, procesado y analitica. Las tres pueden apuntar a los mismos archivos con distintas definiciones.
bash
# ejemplo de referencia
aws glue create-database --database-input '{"Name":"crudo"}'Ver solución
bash
aws glue create-database --database-input '{"Name":"crudo"}'
aws glue get-tables --database-name crudo --query 'length(TableList)' --output text
# 0🔴 Nivel 5 — Los límites del emulador (35-40)
Ejercicio 35 — Intenta crear la tabla con SQL
Usa CREATE EXTERNAL TABLE desde Athena en vez de Glue. ¿Qué ocurre?
💡 ¿Sabías que…? — en AWS es la forma habitual
En Athena real, CREATE EXTERNAL TABLE registra la tabla en Glue automáticamente. Es lo que verás en casi todos los tutoriales.
sql
-- ejemplo de referencia — como seria en AWS
CREATE EXTERNAL TABLE ventas (producto string, total int)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION 's3://otro-lago/ventas/';Ver solución
La consulta se queda en RUNNING y no registra ninguna tabla. En el emulador hay que usar aws glue create-table. Verificado el 2026-08-08.
Ejercicio 36 — Provoca el fallo de memoria
Lanza varias consultas seguidas hasta que el sidecar falle, y lee el error.
💡 ¿Sabías que…? — el sidecar tiene 128 MiB fijos
Floci arranca floci-duck con ese límite y no hay variable para cambiarlo. DuckDB se reserva ~102 MiB y falla al pedir bloques mayores, aunque el host tenga gigas libres.
bash
# ejemplo de referencia — ver el limite
docker inspect floci-duck --format '{{.HostConfig.Memory}}'Ver solución
Out of Memory Error: could not allocate block of size 76.5 MiB (31.5 MiB/102.3 MiB used)Ocurre incluso con un CSV de 349 bytes. No depende del volumen de datos, sino del estado en que quede el sidecar.
Ejercicio 37 — Intenta arreglarlo reiniciando el sidecar
Reinicia el contenedor floci-duck y vuelve a consultar.
💡 ¿Sabías que…? — lo intuitivo no funciona
Reiniciar el contenedor que falla es el primer reflejo. Aquí no basta: el error se repite igual.
bash
# ejemplo de referencia
docker restart floci-duckVer solución
bash
docker restart floci-duck
athena "SELECT COUNT(*) FROM atenciones"
# el mismo Out of Memory ErrorEjercicio 38 — Intenta eliminarlo (y observa que empeora)
Borra el contenedor para que Floci cree uno nuevo. ¿Mejora?
💡 ¿Sabías que…? — Floci recuerda la dirección antigua
Guarda la dirección del sidecar en memoria. Si desaparece, sigue intentando hablar con la IP anterior.
bash
# ejemplo de referencia
docker rm -f floci-duckVer solución
bash
docker rm -f floci-duck
athena "SELECT COUNT(*) FROM atenciones"
# Failed to call floci-duck execute: No route to host (connect failed)Empeora: de un error de memoria pasas a uno de red. Es el peor camino.
Ejercicio 39 — La única salida que funciona
Recupera Athena. ¿Qué precio tiene?
💡 ¿Sabías que…? — reiniciar Floci borra el estado
Todo lo que vive en memoria —buckets, tablas, catálogo— desaparece. Por eso conviene tener el montaje del lago en un script.
bash
# ejemplo de referencia
floci restartVer solución
bash
floci restart
# ...y volver a montar el lago entero: buckets, CSV, base y tabla
athena "SELECT COUNT(*) AS n, SUM(atenciones) AS total FROM atenciones"
# 8 2236La secuencia completa: el sidecar se queda sin memoria → reiniciarlo no basta → eliminarlo lo empeora → solo floci restart lo recupera, a costa de todo el estado.
Ejercicio 40 — Desmontar el lago
Borra los buckets, la tabla y la base del catálogo.
💡 ¿Sabías que…? — el orden importa
Un bucket con objetos no se puede borrar. Hay que vaciarlo primero, o usar --force.
bash
# ejemplo de referencia
aws s3 rb s3://otro-lago --forceVer solución
bash
aws s3 rb s3://clase05-lago --force
aws s3 rb s3://clase05-resultados --force
aws glue delete-table --database-name analitica --name atenciones
aws glue delete-database --name analitica❓ Preguntas y respuestas (autoevaluación)
1. ¿Qué diferencia hay entre un data lake y una base de datos?
El lago guarda archivos parados y arranca un motor solo al consultar; la base tiene un servidor encendido siempre.
2. ¿Qué convierte un CSV en una tabla consultable?
El catálogo (Glue): declara columnas y ubicación. El archivo no se toca ni se copia.
3. ¿Por qué la ubicación de la tabla es una carpeta y no un archivo?
Para que todo lo que caiga dentro entre en las consultas sin volver a registrar nada.
4. ¿Por qué una consulta de Athena es asíncrona?
Porque puede tardar minutos sobre volúmenes grandes. Se lanza, se sondea y se recogen los resultados.
5. ¿Qué contiene la primera fila de get-query-results?
Los nombres de las columnas, no datos. Hay que saltarla al procesar.
6. ¿Por qué SELECT * es peor en Athena que en PostgreSQL?
Porque se factura por bytes leídos: pedir columnas que no usas se paga.
7. ¿LIMIT 1 abarata una consulta?
No. Recorta la respuesta, no el escaneo. Para reducir lo leído hay que filtrar o particionar.
8. Tu consulta devuelve cero filas y ningún error. ¿Primera sospecha?
La ubicación de la tabla: apunta a una carpeta vacía o equivocada.
9. ¿Cómo se recupera Athena tras el fallo de memoria del sidecar?
Solo con
floci restart. Reiniciar el sidecar no basta y eliminarlo lo empeora.
10. ¿Cuándo elegirías Athena y cuándo RDS?
Athena para análisis ocasional de mucho volumen; RDS para una aplicación que consulta constantemente.
📎 Apuntes relacionados
- Clase 2 — RDS · la comparación de velocidad del ejercicio 32
- Clase 4 — API REST · DynamoDB para consultas por clave, Athena para análisis
- Sidecar de DuckDB sin memoria
➡️ Siguiente
Clase 6 — Arquitectura orientada a eventos: que subir un archivo dispare una reacción en cadena, sin que nadie llame a nadie.