Snowflake MigrationClickHouse Workshops
Worksheet perencanaan

Worksheet 3: Terjemahan skema

Petakan setiap kolom TRIPS_RAW dan FACT_TRIPS ke tipe ClickHouse-nya dan terjemahkan tujuh ekspresi Snowflake, dengan umpan balik langsung pada setiap jawaban.

Perkiraan waktu: 20–25 menit Referensi: Snowflake vs ClickHouse — Bagian 2 (SQL Dialect Gaps)

Konsep

Pemetaan tipe dan terjemahan fungsi adalah bagian paling mekanis dari migrasi, tetapi juga paling rawan kesalahan jika dikerjakan sembarangan. Snowflake dan ClickHouse punya sistem tipe yang berbeda dengan semantik yang berbeda, dan memakai tipe yang salah bisa menyebabkan hilangnya presisi secara diam-diam, penyimpanan berlebihan, atau logika query yang rusak.

Prinsip utama:

  1. Bersikap eksplisit soal presisi. TIMESTAMP_NTZ(9) milik Snowflake punya presisi nanodetik. DateTime milik ClickHouse hanya punya presisi detik — jangan pakai itu untuk kolom versi. Gunakan DateTime64(3, 'UTC') untuk presisi milidetik (sesuai dengan sebagian besar kebutuhan nyata) atau DateTime64(9, 'UTC') untuk nanodetik. Ini penting untuk kebenaran hasil: jika kolom versi ReplacingMergeTree hanya punya presisi detik, dua update yang tiba dalam detik yang sama menjadi non-deterministik — ClickHouse tidak bisa menentukan mana yang lebih baru.

  2. Gunakan tipe integer terkecil yang benar. INTEGER milik Snowflake adalah NUMBER(38, 0) — presisi tetap 38 digit yang disimpan sebagai nilai 128-bit. ClickHouse punya integer berlebar tetap: Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64. Memilih UInt8 untuk vendor_id (nilai 1–3) menghemat 7 byte per baris dibanding Int64. Pada 50 juta baris, itu 350MB.

  3. VARIANT → String. ClickHouse punya tipe JSON native (tersedia di v25.3+ sebagai production-stable), tetapi tipe itu dirancang untuk skema yang benar-benar dinamis di mana nama field dan strukturnya tidak diketahui saat tabel dibuat. Untuk trip_metadata di lab ini, strukturnya sudah diketahui (driver.rating, app.surge_multiplier, dan sebagainya) — pendekatan yang lebih baik adalah meratakan lebih dulu menjadi kolom bertipe selama migrasi, atau menyimpannya sebagai String dan memakai JSONExtract* saat query. Gunakan tipe JSON ketika Anda benar-benar tidak bisa memprediksi skemanya: misalnya, mengingest payload event pelanggan yang arbitrer di mana setiap event punya field berbeda. ("Meratakan lebih dulu menjadi kolom bertipe" berarti mengekstrak field menjadi kolom tingkat atas yang terpisah selama ETL — seperti cara FACT_TRIPS.driver_rating dihasilkan dari trip_metadata — bukan membungkus blob JSON itu sendiri dalam sebuah Tuple. Kolom Tuple tetap mengikat diri pada satu set field yang tetap, sehingga ia rusak begitu metadata sebuah perjalanan tidak cocok dengan bentuk itu.)

  4. Presisi float. FLOAT milik Snowflake dipetakan ke Float64 di ClickHouse. Untuk nilai uang yang menuntut aritmetika desimal eksak, gunakan Decimal(18, 2) — tetapi untuk lab ini, Float64 sudah cukup untuk menyamai sumbernya. (Ini adalah default, bukan aturan bahwa setiap kolom FLOAT mengambil Float64 tanpa memandang rentangnya: sebuah kolom seperti driver_rating, yang nilainya berjalan 1.0–5.0 pada satu angka desimal, cukup nyaman masuk ke ~7 digit signifikan milik Float32 — pilihan di sana bergantung pada nullability, bukan pada presisi yang dilindungi Aturan 4 untuk nilai uang.)

  5. LowCardinality() — optimasi khusus ClickHouse. Membungkus sebuah tipe dalam LowCardinality(String) (atau LowCardinality(UInt8), dan sebagainya) memberitahu ClickHouse untuk memakai dictionary encoding bagi kolom itu — nilai disimpan sebagai referensi integer ke sebuah dictionary, bukan sebagai string yang berulang. Ini biasanya memberi perbaikan kompresi 2–5x dan GROUP BY yang lebih cepat pada kolom string dengan kurang dari ~10.000 nilai berbeda. Snowflake tidak punya padanannya; ia menanganinya secara otomatis. Kandidat yang baik di lab ini: pickup_borough (6 nilai), payment_type (6 nilai), vehicle_type, vendor_name.

Latihan: pemetaan tipe untuk TRIPS_RAW

Petakan setiap kolom dari NYC_TAXI_DB.RAW.TRIPS_RAW ke tipe ClickHouse-nya. TRIP_ID sudah diisi sebagai contoh: String adalah pilihan idiomatis saat bermigrasi dari VARCHAR(36) — ia tidak butuh casting, mendukung setiap fungsi string, dan menghindari overhead parsing UUID saat insert, meskipun ClickHouse juga punya tipe UUID native.

Latihan: pemetaan tipe untuk FACT_TRIPS

FACT_TRIPS menambahkan kolom terhitung/turunan yang ditambahkan oleh pipeline dbt. Sebagian besar kolom mengulang keputusan TRIPS_RAW; DRIVER_RATING dan UPDATED_AT adalah yang baru.

DRIVER_RATING sering kali NULL (tidak ada rating yang diberikan). Di ClickHouse, Nullable(Float64) punya sedikit overhead performa dibanding kolom non-nullable — sebuah bitmask terpisah disimpan bersama data untuk melacak baris mana yang null. Pilihan untuk kolom ini adalah antara Nullable(Float32) (semantik null yang eksplisit) dan Float32 polos dengan nilai sentinel seperti -1.0 (lebih cepat, kurang konvensional). Lab ini memakai Nullable(Float32) demi kebenaran hasil.

Latihan: terjemahan fungsi

Terjemahkan setiap ekspresi Snowflake ke padanan ClickHouse-nya. Ini datang langsung dari Q1–Q7 di 01-setup-snowflake/queries/. Tiga dari delapan — QUALIFY, MERGE INTO, dan pembacaan stream CDC — tidak punya ekspresi satu baris sebagai jawabannya, jadi ketiganya dikerjakan sebagai pertanyaan di bawah tabel.

Pertanyaan refleksi

Setelah tabel di atas terisi, kerjakan pertanyaan berikut. Tiga di antaranya berasal dari terjemahan Latihan 3 yang butuh lebih dari satu baris untuk dijawab; tiga lainnya adalah "Non-Obvious Translation Decisions" dari worksheet sumber — penalaran di balik pilihan tipe TRIP_METADATA, FARE_AMOUNT, dan PICKUP_LOCATION_ID di atas.

Loading worksheet...

Pindahkan ke migration-plan.md

Salin keputusan tipe Anda dan setiap catatan terjemahan yang tidak kasatmata ke Bagian 5 dari migration-plan.md dan centang:

- [ ] Schema translation: completed

Di halaman ini

Track your progress?

Optional. We email a link to confirm your address; progress records once you open it.

Please use your work email address, not a personal one.

Progress tracking also requires accepting the current Terms of Service in Privacy settings.

ID