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:
-
Indica expresamente la precisión.
TIMESTAMP_NTZ(9)de Snowflake ofrece precisión de nanosegundos;DateTimede ClickHouse solo llega al segundo, por lo que no debes utilizarlo para columnas de versión. UsaDateTime64(3, 'UTC')para obtener precisión de milisegundos, que coincide con la mayoría de los requisitos reales, oDateTime64(9, 'UTC')si necesitas nanosegundos. Esto afecta a la corrección: si una columna de versión deReplacingMergeTreesolo 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. -
Usa el tipo entero correcto más pequeño.
INTEGERde Snowflake equivale aNUMBER(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. ElegirUInt8paravendor_id, cuyos valores van de 1 a 3, ahorra 7 bytes por fila frente aInt64. En 50 millones de filas, el ahorro alcanza 350 MB. -
VARIANT → String. ClickHouse dispone de un tipo
JSONnativo, 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 detrip_metadata(driver.rating,app.surge_multiplier, etc.): resulta preferible preaplanarla en columnas tipadas durante la migración, o almacenarla comoStringy emplearJSONExtract*al consultar. UsaJSONcuando 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 generaFACT_TRIPS.driver_ratinga partir detrip_metadata—, no envolver el blob JSON en unTuple. Una columnaTupletambién impone un conjunto fijo de campos y deja de funcionar cuando los metadatos de un viaje no coinciden con esa forma. -
Precisión de coma flotante.
FLOATde Snowflake se mapea aFloat64en ClickHouse. Para importes monetarios que requieran aritmética decimal exacta, utilizaDecimal(18, 2); en este laboratorio, sin embargo,Float64es suficiente para reproducir el origen. Este criterio es un valor predeterminado, no una regla que obligue a asignarFloat64a cualquier columnaFLOATcon independencia de su intervalo. Una columna comodriver_rating, cuyos valores van de 1,0 a 5,0 con un decimal, cabe holgadamente en los aproximadamente 7 dígitos significativos deFloat32; en ese caso, la elección depende de la nulabilidad y no de la precisión que esta cuarta regla protege para el dinero. -
LowCardinality(): optimización exclusiva de ClickHouse.LowCardinality(String)(oLowCardinality(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 aceleraGROUP BYen 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 candidataspickup_borough(6 valores),payment_type(6 valores),vehicle_typeyvendor_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