Snowflake MigrationClickHouse Workshops
Hojas de planificación

Hoja 3: traducción del esquema

Mapea cada columna de TRIPS_RAW y FACT_TRIPS y traduce siete expresiones Snowflake, con comentarios inmediatos.

Tiempo estimado: 20–25 minutos Referencia: Snowflake frente a ClickHouse, Sección 2 sobre diferencias SQL

Concepto

El mapeo de tipos y la traducción de funciones son la parte más mecánica de una migración, pero también la más propensa a errores si se realiza sin cuidado. Snowflake y ClickHouse tienen sistemas de tipos distintos y con semánticas diferentes; elegir un tipo equivocado puede provocar una pérdida silenciosa de precisión, un consumo excesivo de almacenamiento o una lógica de consultas incorrecta.

Principios clave:

  1. Indica expresamente la precisión. TIMESTAMP_NTZ(9) de Snowflake ofrece precisión de nanosegundos; DateTime de ClickHouse solo llega al segundo, por lo que no debes utilizarlo para columnas de versión. Usa DateTime64(3, 'UTC') para obtener precisión de milisegundos, que coincide con la mayoría de los requisitos reales, o DateTime64(9, 'UTC') si necesitas nanosegundos. Esto afecta a la corrección: si una columna de versión de ReplacingMergeTree solo tiene precisión de segundos, dos actualizaciones que lleguen dentro del mismo segundo producen un resultado no determinista, porque ClickHouse no puede decidir cuál es la más reciente.

  2. Usa el tipo entero correcto más pequeño. INTEGER de Snowflake equivale a NUMBER(38, 0): una precisión fija de 38 dígitos almacenada en un valor de 128 bits. ClickHouse ofrece enteros de anchura fija: Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64. Elegir UInt8 para vendor_id, cuyos valores van de 1 a 3, ahorra 7 bytes por fila frente a Int64. En 50 millones de filas, el ahorro alcanza 350 MB.

  3. VARIANT → String. ClickHouse dispone de un tipo JSON nativo, estable para producción desde la versión 25.3, pero está pensado para esquemas verdaderamente dinámicos en los que los nombres y la estructura de los campos se desconocen al crear la tabla. En este laboratorio se conoce la estructura de trip_metadata (driver.rating, app.surge_multiplier, etc.): resulta preferible preaplanarla en columnas tipadas durante la migración, o almacenarla como String y emplear JSONExtract* al consultar. Usa JSON cuando realmente no puedas predecir el esquema, por ejemplo al ingerir cargas arbitrarias de eventos de clientes donde cada evento tiene campos distintos. «Preaplanar en columnas tipadas» significa extraer los campos a columnas independientes de nivel superior durante el ETL —como se genera FACT_TRIPS.driver_rating a partir de trip_metadata—, no envolver el blob JSON en un Tuple. Una columna Tuple también impone un conjunto fijo de campos y deja de funcionar cuando los metadatos de un viaje no coinciden con esa forma.

  4. Precisión de coma flotante. FLOAT de Snowflake se mapea a Float64 en ClickHouse. Para importes monetarios que requieran aritmética decimal exacta, utiliza Decimal(18, 2); en este laboratorio, sin embargo, Float64 es suficiente para reproducir el origen. Este criterio es un valor predeterminado, no una regla que obligue a asignar Float64 a cualquier columna FLOAT con independencia de su intervalo. Una columna como driver_rating, cuyos valores van de 1,0 a 5,0 con un decimal, cabe holgadamente en los aproximadamente 7 dígitos significativos de Float32; en ese caso, la elección depende de la nulabilidad y no de la precisión que esta cuarta regla protege para el dinero.

  5. LowCardinality(): optimización exclusiva de ClickHouse. LowCardinality(String) (o LowCardinality(UInt8), etc.) usa codificación por diccionario: los valores se almacenan como referencias enteras a un diccionario, en lugar de repetir cadenas. Normalmente mejora la compresión entre 2 y 5 veces y acelera GROUP BY en columnas de texto con menos de unos 10 000 valores distintos. Snowflake no tiene un equivalente visible porque gestiona esta optimización automáticamente. En el laboratorio son buenas candidatas pickup_borough (6 valores), payment_type (6 valores), vehicle_type y vendor_name.

Ejercicio: tipos para TRIPS_RAW

Mapea cada columna de NYC_TAXI_DB.RAW.TRIPS_RAW a su tipo de ClickHouse. TRIP_ID aparece resuelta como ejemplo: al migrar desde VARCHAR(36), String es la opción idiomática porque no exige conversiones, admite todas las funciones de cadenas y evita el coste de analizar un UUID durante cada inserción, aunque ClickHouse también disponga de un tipo UUID nativo.

Ejercicio: tipos para FACT_TRIPS

FACT_TRIPS añade columnas calculadas o derivadas que generó la canalización de dbt. La mayoría de las columnas repiten una decisión tomada para TRIPS_RAW; DRIVER_RATING y UPDATED_AT son nuevas.

DRIVER_RATING contiene con frecuencia NULL, porque no siempre se facilita una valoración. En ClickHouse, Nullable(Float64) impone una pequeña sobrecarga respecto a una columna no anulable: junto a los datos se almacena una máscara de bits separada que indica qué filas son nulas. La elección para esta columna está entre Nullable(Float32), con semántica explícita de valores nulos, y un Float32 sin envoltura que utilice un valor centinela como -1.0, más rápido pero menos convencional. El laboratorio utiliza Nullable(Float32) para preservar la corrección.

Ejercicio: traducción de funciones

Traduce cada expresión de Snowflake a su equivalente en ClickHouse. Proceden directamente de Q1–Q7 en 01-setup-snowflake/queries/. Tres de las ocho —QUALIFY, MERGE INTO y la lectura del stream de CDC— no tienen una expresión de una sola línea como respuesta, por lo que se plantean como preguntas debajo de la tabla.

Preguntas de reflexión

Después de completar las tablas anteriores, responde estas preguntas. Tres proceden de las traducciones del Ejercicio 3 que requerían más de una línea; las otras tres son las «decisiones de traducción no obvias» de la hoja de origen, es decir, el razonamiento que sustenta las elecciones de tipo para TRIP_METADATA, FARE_AMOUNT y PICKUP_LOCATION_ID.

Loading worksheet...

Transfiérelo a migration-plan.md

Copia tus decisiones de tipos y todas las notas de traducción no obvias en la Sección 5 de migration-plan.md y marca:

- [ ] Schema translation: completed

En esta página

¿Quieres seguir tu progreso?

Opcional. Enviaremos un enlace por correo para confirmar tu dirección; el progreso se registrará cuando lo abras.

Usa tu correo de trabajo, no uno personal.

Para seguir el progreso también debes aceptar los Términos del servicio actuales en la Configuración de privacidad.

ES