Skip to Content

SQL Execution Plans EXPLAINED

Halo, kawan-kawan! Senang sekali bisa berbagi tentang topik yang sangat fundamental namun sering diabaikan: Execution Plan.

Banyak dari kita jago menulis kueri SQL yang kompleks. Kita bisa melakukan join berlapis, agregasi yang rumit, dan subquery yang canggih. Tapi, ada satu pertanyaan yang sering menghantui:

"Kueri saya sudah benar, tapi kenapa lambat sekali?"

Kita lalu menebak-nebak. "Mungkin kurang indeks di kolom A," atau "Mungkin join-nya harus diubah." Kita mencoba-coba, dan akhirnya kueri itu cepat. Tapi apakah kita benar-benar tahu mengapa itu menjadi cepat? Atau kita hanya beruntung?

Di sinilah Execution Plan berperan. Ini adalah alat diagnostik paling kuat yang Anda miliki. Ini adalah jendela untuk melihat bagaimana database SQL Anda berpikir.

Saya di sini bukan hanya untuk memberi tahu Anda apa itu Execution Plan. Saya ingin menunjukkan kepada Anda cara membacanya seperti seorang detektif, menemukan "biang kerok" performa, dan membuat keputusan indexing yang tepat berdasarkan data, bukan tebakan.

Mari kita bedah bersama.

🧠 Bagian 1: Apa Itu Execution Plan? Jendela Menuju Pikiran Database

Saat Anda menjalankan kueri SELECT, database tidak langsung mengambil data. Tidak. Sama seperti Anda merencanakan rute di Google Maps sebelum berangkat, database akan membuat sebuah rencana terlebih dahulu.

Rencana inilah yang disebut Execution Plan (Rencana Eksekusi).

Ini adalah peta jalan langkah-demi-langkah yang dibuat oleh Query Optimizer (mesin pengoptimal kueri) untuk mendapatkan data yang Anda minta dengan cara seefisien mungkin. Rencana ini menentukan segalanya:

  • Bagaimana cara mengakses data dari tiap tabel? (Apakah memindai seluruh tabel atau langsung melompat ke data spesifik?)
  • Apa urutan join tabelnya? (Apakah tabel A di-join ke B dulu, atau B ke C?)
  • Metode join apa yang dipakai? (Apakah menggunakan Nested Loop, Merge Join, atau Hash Join?)
  • Bagaimana data akan diurutkan atau diagregasi?

Sudut Pandang yang Jarang Dilihat: Rencana Itu "Mahal"

Membuat rencana ini sendiri adalah proses yang memakan sumber daya (CPU dan memori). Karena itu, setelah sebuah rencana dibuat dan dieksekusi, SQL Server akan menyimpannya di cache.

Jika Anda atau pengguna lain menjalankan kueri yang identik (atau sangat mirip), database akan berkata, "Ah, saya sudah punya rencana untuk ini!" dan langsung menggunakan rencana dari cache tadi. Ini jauh lebih cepat daripada harus membuatnya dari nol. Inilah mengapa menjalankan kueri untuk kedua kalinya seringkali terasa instan.

👉 Apa yang bisa kamu lakukan sekarang:

Mulailah mengubah cara pandang Anda. Jangan hanya fokus pada hasil kueri, tapi mulailah penasaran dengan proses di baliknya. Setiap kali Anda menulis kueri, tanyakan: "Kira-kira, bagaimana database akan menjalankannya?"

🔬 Bagian 2: Tiga Tipe Rencana Eksekusi (Mana yang Dipakai?)

Di SQL Server Management Studio (SSMS), Anda akan melihat tiga tombol utama untuk ini. Penting untuk tahu bedanya.

  1. Display Estimated Execution Plan (Perkiraan Rencana):
    • Ini adalah tebakan atau prediksi database tentang rencana yang mungkin akan digunakannya.
    • Kueri Anda tidak dijalankan. Ini hanya simulasi.
    • Berguna untuk kueri UPDATE atau DELETE yang berbahaya jika dijalankan sungguhan hanya untuk melihat rencananya.
  2. Include Actual Execution Plan (Rencana Aktual):
    • Ini adalah rencana yang sebenarnya digunakan oleh database.
    • Kueri Anda akan dijalankan terlebih dahulu, baru rencananya ditampilkan.
    • Ini adalah alat utama kita, karena menunjukkan apa yang benar-benar terjadi, lengkap dengan statistik aktual (misalnya, berapa baris yang sebenarnya dibaca).
  3. Include Live Query Statistics (Statistik Kueri Langsung):
    • Ini menunjukkan rencana eksekusi secara real-time saat kueri sedang berjalan.
    • Anda bisa melihat data mengalir dari satu operator ke operator lain. Sangat berguna untuk kueri yang berjalan sangat lama (menit/jam) untuk melihat di mana letak kemacetannya.

Sudut Pandang yang Jarang Dilihat: Waspada Jika "Perkiraan" vs "Aktual" Berbeda!

Ini adalah red flag besar. Jika Anda membandingkan Rencana Perkiraan dengan Rencana Aktual dan keduanya berbeda jauh (misalnya, yang satu memprediksi 10 baris tapi nyatanya memproses 10 juta baris), ini pertanda kuat bahwa statistik database Anda sudah usang (outdated).

Database membuat rencana berdasarkan statistik (data tentang distribusi data di tabel Anda). Jika statistiknya salah, rencananya akan salah. Ini seperti Google Maps memberi Anda rute berdasarkan data lalu lintas minggu lalu.

👉 Apa yang bisa kamu lakukan sekarang:

Mulai sekarang, biasakan untuk selalu menggunakan "Include Actual Execution Plan" (Ctrl+M) untuk setiap kueri SELECT yang Anda analisis. Ini adalah kebenaran di lapangan.

📖 Bagian 3: Kamus Wajib: Membaca Rencana Eksekusi (Kanan ke Kiri)

Membaca Execution Plan itu seperti membaca komik manga: dari kanan ke kiri, dan dari atas ke bawah.

Operator paling kanan adalah hal pertama yang dieksekusi (biasanya mengambil data dari tabel), dan operator paling kiri adalah hasil akhirnya (data yang Anda lihat).

Setiap ikon adalah "Operator" yang melakukan satu tugas spesifik. Berikut adalah operator paling umum yang wajib Anda kenali:

1. Operator Pengambilan Data (Akses Tabel)

Ini adalah cara SQL Server membaca data Anda. Perhatikan baik-baik, karena ini adalah sumber masalah paling umum.

  • Table Scan (Ikon Merah 🚨):
    • Apa artinya: SQL Server membaca seluruh tabel dari baris pertama hingga terakhir.
    • Kapan terjadi: Biasanya pada tabel Heap (tabel yang tidak memiliki Clustered Index).
    • Analogi: Mencari satu buku di perpustakaan tanpa katalog, jadi Anda harus memeriksa setiap buku di setiap rak.
    • Putusan: Sangat buruk untuk tabel besar.
  • Clustered Index Scan (Ikon Kuning ⚠️):
    • Apa artinya: SQL Server membaca seluruh Clustered Index (yaitu, seluruh data tabel, karena data disimpan di dalam Clustered Index).
    • Kapan terjadi: Saat Anda SELECT * tanpa WHERE, atau saat klausa WHERE Anda tidak dapat menggunakan indeks.
    • Putusan: Sama buruknya dengan Table Scan jika tujuannya mencari data spesifik, tapi wajar jika Anda memang butuh semua data.
  • Index Seek (Ikon Hijau ✅):
    • Apa artinya: SQL Server menggunakan indeks (seperti B-Tree) untuk langsung melompat ke baris data yang Anda butuhkan.
    • Kapan terjadi: Saat klausa WHERE Anda sangat spesifik dan ada indeks yang mendukungnya.
    • Analogi: Mencari buku di perpustakaan menggunakan katalog. Anda tahu persis rak dan lokasinya.
    • Putusan: Inilah "Cawan Suci" performa kueri. Ini yang selalu kita inginkan.

2. Operator "Perangkap" (Waspada!)

  • Key Lookup (Ikon Kuning ⚠️):
    • Apa artinya: Ini adalah operasi berpasangan. Biasanya terjadi setelah Index Seek pada non-clustered index.
    • Kenapa? Index Seek berhasil menemukan baris yang Anda cari di non-clustered index. TAPI, kueri Anda meminta kolom lain (SELECT * atau SELECT KolomLain) yang tidak ada di dalam indeks tersebut.
    • Jadi, SQL Server harus mengambil "kunci" dari hasil Seek dan menggunakannya untuk "melihat" kembali ke tabel utama (Clustered Index) untuk mengambil sisa kolomnya.
    • Putusan: Ini bisa sangat mahal! Jika Index Seek mengembalikan 10.000 baris, akan ada 10.000 operasi Key Lookup.

3. Operator Join (Internal)

Ini bukan INNER JOIN atau LEFT JOIN Anda. Ini adalah metode fisik yang digunakan database untuk menggabungkan dua set data.

  • Nested Loops:
    • Cara kerja: Ambil satu baris dari tabel luar, lalu cari pasangannya di tabel dalam. Ulangi untuk setiap baris di tabel luar.
    • Kapan bagus: Sangat efisien jika set data "luar" sangat kecil (misal, 10 baris).
    • Kapan buruk: Bencana jika kedua tabel besar.
  • Merge Join:
    • Cara kerja: Menggabungkan dua set data yang sudah terurut (seperti menggabungkan dua tumpukan kartu yang sudah urut).
    • Kapan bagus: Sangat cepat jika kedua input sudah terurut (misalnya, berasal dari Clustered Index Scan pada kolom join). Jika belum urut, SQL akan menambahkan operator Sort yang mahal.
  • Hash Match:
    • Cara kerja: Membangun "tabel hash" (seperti kamus) di memori dari tabel yang lebih kecil, lalu memindai tabel besar untuk mencari kecocokan di tabel hash tersebut.
    • Kapan bagus: "Pekerja keras" untuk set data besar yang tidak terurut. Ini adalah join serba guna yang paling umum.

👉 Apa yang bisa kamu lakukan sekarang:

  1. Ambil salah satu kueri Anda.
  2. Aktifkan "Actual Execution Plan".
  3. Jalankan kueri.
  4. Lihat tab "Execution Plan". Baca dari kanan ke kiri.
  5. Cari Operator termahal. Arahkan kursor Anda ke setiap ikon, cari yang memiliki Estimated Subtree Cost paling tinggi. Di situlah masalah Anda dimulai. Apakah itu Table Scan? Clustered Index Scan? Sort?

📊 Bagian 4: Studi Kasus - Kekuatan Indeks (Row-Store vs. Columnstore)

Seperti yang kita lihat di video, kita bisa membuktikan nilai indeks secara visual.

Kasus 1: ORDER BY pada Kunci Primer

  • Tabel Heap (Tanpa Indeks): Rencananya adalah Table Scan -> Sort. Operator Sort ini sangat mahal karena harus memuat semua 60.000 baris ke memori untuk diurutkan.
  • Tabel Clustered Index (Indeks di PK): Rencananya hanya Clustered Index Scan. Tidak ada operator Sort! Kenapa? Karena data di Clustered Index sudah tersimpan dalam keadaan terurut. Ini adalah "kemenangan" besar.

Kasus 2: WHERE pada Kolom Non-Indeks vs. Indeks

  • Tabel Heap: Table Scan. Membaca 60.000 baris untuk menemukan 12 baris.
  • Tabel dengan Non-Clustered Index (di kolom WHERE): Index Seek! Membaca hanya 12 baris untuk mendapatkan 12 baris. Ini efisiensi 100%. Tetapi, karena kita SELECT *, muncul Key Lookup untuk mengambil sisa kolom.

Kasus 3: Agregasi pada Tabel Fakta (Row-Store vs. Columnstore)

  • Masalah: Kita punya kueri analitik (JOIN tabel Fakta ke Dimensi, lalu GROUP BY dan SUM).
  • Plan (Row-Store): Clustered Index Scan pada tabel Fakta memakan 71% dari total biaya kueri. Ini adalah biang keroknya.
  • Solusi: Kita ubah tabel Fakta menjadi Clustered Columnstore Index.
  • Plan (Columnstore): Columnstore Index Scan pada tabel Fakta sekarang hanya memakan 6% dari total biaya!
  • Sudut Pandang Saya: Ini bukan sihir. Columnstore dirancang untuk analitik. Ia hanya membaca kolom yang Anda butuhkan (misal, SalesAmount dan ProductKey), bukan seluruh baris seperti Row-Store. Untuk kueri SUM pada tabel 1 Miliar baris, perbedaannya adalah antara beberapa detik dan beberapa jam.

👉 Apa yang bisa kamu lakukan sekarang:

  1. Periksa kueri Anda yang menggunakan WHERE. Apakah rencananya Scan atau Seek? Jika Scan, buatlah non-clustered index pada kolom di klausa WHERE Anda. Jalankan lagi kuerinya dan lihat rencananya berubah menjadi Index Seek.
  2. Jika Anda melihat pasangan Index Seek + Key Lookup yang mahal (misalnya, 90% biaya ada di Key Lookup), pertimbangkan untuk membuat Covering Index. Ini adalah non-clustered index yang menyertakan kolom yang Anda SELECT menggunakan klausa INCLUDE. Ini akan menghilangkan Key Lookup sepenuhnya.
  3. Jika Anda memiliki tabel Fact yang besar (jutaan/miliaran baris) dan sering digunakan untuk agregasi (SUM, COUNT, AVG), pertimbangkan dengan serius untuk menggunakan Columnstore Index.

🛑 Bagian 5: Sudut Pandang Saya - Bahaya Tersembunyi SQL Hints

Terkadang, Anda tahu lebih baik daripada Query Optimizer. Mungkin statistiknya usang, atau kuerinya terlalu kompleks sehingga Optimizer "menyerah" dan memilih rencana yang buruk.

Anda bisa "memaksa" database menggunakan rencana Anda dengan SQL Hints, seperti:

  • OPTION (USE HASH JOIN)
  • WITH (FORCESEEK)
  • WITH (INDEX(NamaIndeksAnda))

Ini terlihat sangat keren, tapi dengarkan pengalaman saya: Hati-hati!

SQL Hints adalah pedang bermata dua.

  1. Bencana Beda Lingkungan: Hint yang membuat kueri Anda terbang di Development (data 10.000 baris) bisa menjadi bencana di Production (data 100 juta baris). Distribusi data yang berbeda membutuhkan rencana yang berbeda. Dengan hint, Anda mengunci satu rencana dan membunuh kemampuan adaptasi Optimizer.
  2. Perban, Bukan Solusi: Hint seringkali hanya menutupi masalah mendasar. Jika Anda perlu FORCESEEK, mungkin statistik Anda yang perlu diperbarui. Jika Anda perlu USE HASH JOIN, mungkin desain indeks Anda yang salah.

Rekomendasi Saya: Gunakan SQL Hints hanya sebagai solusi sementara (workaround) dalam keadaan darurat. Jangan pernah menganggapnya sebagai solusi permanen. Prioritas Anda selalu mencari akar masalahnya.

👉 Apa yang bisa kamu lakukan sekarang:

Jika Anda menemukan kueri lambat yang "membaik" dengan hint, jangan berhenti di situ. Tanyakan, "Mengapa Optimizer tidak memilih rencana ini secara otomatis?" Jawabannya hampir selalu: "Statistik Usang" atau "Desain Indeks yang Hilang/Salah". Perbaiki akarnya.

✅ Checklist Praktis: Mulai Optimasi Hari Ini

Siap menjadi detektif performa? Ini adalah call to action Anda.

  1. Identifikasi Target: Ambil 1 kueri lambat yang sering Anda jalankan.
  2. Aktifkan Rencana: Buka SSMS, tekan Ctrl+M (Include Actual Execution Plan).
  3. Eksekusi & Baca: Jalankan kueri. Pindah ke tab "Execution Plan". Baca dari kanan ke kiri.
  4. Temukan Biang Kerok: Arahkan kursor ke setiap operator. Cari operator dengan persentase biaya (Cost: X%) tertinggi. Apakah itu Table Scan? Sort? Key Lookup? Hash Match?
  5. Buat Hipotesis:
    • Jika Table Scan atau Index Scan (dan Anda memfilter data): "Saya perlu non-clustered index di kolom WHERE saya."
    • Jika Sort (dan Anda ORDER BY): "Saya perlu indeks di kolom ORDER BY saya."
    • Jika Key Lookup (dan Anda SELECT beberapa kolom): "Saya perlu membuat covering index dengan klausa INCLUDE."
    • Jika Scan di tabel Fakta untuk agregasi: "Saya mungkin perlu Columnstore Index."
  6. Uji & Validasi: Buat indeks yang Anda usulkan (di development!). Jalankan kueri lagi. Lihat Execution Plan-nya berubah. Apakah Scan menjadi Seek? Apakah Sort hilang? Apakah biayanya turun drastis?

Selamat, Anda baru saja berhenti menebak-nebak dan mulai melakukan optimasi berbasis fakta.


📚 Glosarium Detektif SQL: Dari Awam Menjadi Paham

Berikut adalah istilah-istilah kunci dari materi tadi, dipecah dengan analogi agar mudah menempel di kepala.

Grup 1: Konsep Dasar (Otak & Rencana)

1. Execution Plan (Rencana Eksekusi)

  • Definisi Sederhana: Peta jalan atau resep "langkah-demi-langkah" yang dibuat oleh database untuk mengambil data yang Anda minta.
  • Analogi: Saat Anda meminta Google Maps rute dari Purworejo ke Yogyakarta, Google Maps tidak langsung menyuruh Anda jalan. Ia akan menghitung rute terbaik terlebih dahulu (lewat Wates atau lewat Klaten? mana yang lebih cepat?). "Execution Plan" adalah rute yang ia pilihkan.
  • Kapan Ini Penting: Jika kueri Anda lambat, Anda perlu melihat "rute" (Plan) ini untuk mencari tahu di mana letak "kemacetannya".

2. Query Optimizer (Mesin Pengoptimal Kueri)

  • Definisi Sederhana: "Otak" di dalam database yang tugasnya membuat Execution Plan.
  • Analogi: Inilah "mesin" Google Maps itu sendiri. Ia mempertimbangkan data lalu lintas (Statistik), pilihan jalan (Indeks), dan tujuan Anda (Kueri Anda) untuk menghasilkan rute tercepat.
  • Kapan Ini Penting: Anda tidak berinteraksi langsung dengannya, tapi Anda harus paham bahwa "Otak" ini bisa salah mengambil keputusan jika data yang ia miliki (Statistik) sudah usang.

3. Statistics (Statistik)

  • Definisi Sederhana: Data tentang data Anda. Ini adalah rangkuman yang memberi tahu Optimizer seberapa banyak data yang ada, seberapa unik datanya, dan bagaimana distribusinya.
  • Analogi: Ini adalah data "lalu lintas real-time" yang dipakai Google Maps. Tanpa ini, Google Maps mungkin akan mengarahkan Anda ke jalan yang macet total, karena ia mengira jalan itu kosong (berdasarkan data minggu lalu).
  • Kapan Ini Penting: Jika Statistik Anda usang (misalnya, tabel yang tadinya 100 baris sekarang 10 juta baris), Optimizer akan membuat rencana yang sangat buruk karena didasarkan pada asumsi yang salah.

Grup 2: Cara Penyimpanan Data (Gudang)

4. Heap (Tabel Tumpukan)

  • Definisi Sederhana: Tabel yang tidak memiliki susunan fisik. Data dimasukkan begitu saja tanpa diurutkan.
  • Analogi: Tumpukan baju kotor di kamar Anda. Baju baru diletakkan di atas tumpukan. Saat Anda mencari kaos kaki spesifik, Anda harus membongkar seluruh tumpukan untuk menemukannya.
  • Kapan Ini Penting: Mencari data di tabel Heap selalu berujung pada Table Scan (membaca seluruh tabel), yang sangat lambat untuk tabel besar.

5. Clustered Index (Indeks Terklaster)

  • Definisi Sederhana: Indeks yang mengurutkan dan menyimpan data fisik tabel. Sebuah tabel hanya bisa punya satu Clustered Index.
  • Analogi: Lemari arsip (misal, untuk CV Global Sejahtera) yang diurutkan berdasarkan alfabet nama pelanggan (A, B, C...). Map "Faisal" adalah datanya, dan lokasinya sudah pasti di antara "Fadil" dan "Faris". Data fisik tabel adalah indeks itu sendiri.
  • Kapan Ini Penting: Ini menentukan bagaimana data Anda disimpan secara fisik di disk. Jika Anda ORDER BY kolom ini, kueri akan instan karena datanya sudah terurut.

6. Non-Clustered Index (Indeks Non-Klaster)

  • Definisi Sederhana: Struktur terpisah dari tabel (seperti salinan) yang hanya berisi kolom yang diindeks dan "penunjuk" ke baris data aslinya.
  • Analogi: Ini adalah indeks di halaman belakang buku teks. Jika Anda mencari topik "Trading Psychology", Anda tidak membaca seluruh buku. Anda pergi ke halaman indeks, cari "T", temukan "Trading Psychology", dan di sana tertulis: "halaman 50, 112, 203". Anda lalu melompat langsung ke halaman-halaman tersebut.
  • Kapan Ini Penting: Ini adalah cara utama Anda mempercepat WHERE, JOIN, dan ORDER BY pada kolom yang bukan Clustered Index.

Grup 3: Cara Pengambilan Data (Operator)

7. Table Scan (Pindai Tabel)

  • Status: 🔴 BURUK
  • Definisi Sederhana: Membaca setiap baris dalam tabel untuk menemukan data yang Anda cari.
  • Studi Kasus: Anda mencari 1 pelanggan bernama 'Faisal' di tabel Pelanggan (sebuah Heap) yang berisi 5 juta baris. Database terpaksa membaca semua 5 juta baris itu satu per satu hanya untuk menemukan 1 baris.

8. Index Scan (Pindai Indeks)

  • Status: 🟡 HATI-HATI
  • Definisi Sederhana: Membaca seluruh indeks dari awal sampai akhir.
  • Studi Kasus: Anda SELECT * FROM Pelanggan. Database akan membaca seluruh Clustered Index (karena itu adalah datanya). Ini wajar jika Anda memang butuh semua data, tapi buruk jika Anda sebenarnya hanya butuh 1% data.

9. Index Seek (Cari Indeks)

  • Status: 🟢 BAGUS
  • Definisi Sederhana: Menggunakan struktur B-Tree (seperti pencarian biner) pada indeks untuk langsung melompat ke data yang dibutuhkan.
  • Studi Kasus: Anda mencari WHERE SalesOrderNumber = 'SO-123'. Karena SalesOrderNumber adalah Primary Key (dan Clustered Index), database langsung melompat ke data itu. Ia hanya membaca 1 baris, bukan 60.000 baris. Inilah "Cawan Suci" performa kueri.

10. Key Lookup (Pencarian Kunci)

  • Status: 🟡 PERANGKAP!
  • Definisi Sederhana: Operasi tambahan yang mahal. Ini terjadi saat Anda Index Seek di Non-Clustered Index, tapi Anda meminta kolom yang tidak ada di indeks itu.
  • Studi Kasus: Anda punya Non-Clustered Index di kolom CarrierTrackingNumber. Anda menjalankan:
    SELECT * FROM FactResellerSales WHERE CarrierTrackingNumber = 'XYZ'
    1. Index Seek (Cepat): Database menemukan 'XYZ' di indeks.
    2. Key Lookup (Lambat): Indeks 'XYZ' hanya punya penunjuk. Tapi Anda minta SELECT * (semua kolom lain seperti SalesAmount, OrderDate, dll).
    3. Database terpaksa mengambil penunjuk itu, lalu "kembali lagi" ke tabel utama (Clustered Index) untuk mengambil sisa kolomnya. Jika Seek tadi menghasilkan 1.000 baris, akan ada 1.000 Key Lookup! Ini seringkali lebih lambat daripada Scan.

Grup 4: Cara Menggabungkan Data (Join Internal)

11. Nested Loops (Join Bersarang)

  • Analogi: "Siklus di dalam siklus".
  • Cara Kerja: Ambil 1 baris dari tabel luar (misal, DimProduct), lalu cari semua pasangannya di tabel dalam (misal, FactSales). Ulangi untuk baris kedua DimProduct, cari lagi di FactSales, dan seterusnya.
  • Kapan Bagus: Sangat cepat jika tabel "luar" sangat kecil (misal, 10 produk) dan tabel "dalam" punya indeks yang bagus.
  • Kapan Buruk: Bencana jika kedua tabel besar.

12. Merge Join (Join Gabung)

  • Analogi: "Ritsleting".
  • Cara Kerja: Menggabungkan dua set data yang keduanya sudah terurut pada kolom join.
  • Kapan Bagus: Sangat cepat jika kedua input (misal, dari Clustered Index) sudah terurut. Jika belum, database akan menambahkan operator Sort yang mahal.

13. Hash Match (Join Hash)

  • Analogi: "Daftar Contekan" atau "Kamus".
  • Cara Kerja: Ambil tabel yang lebih kecil (misal, DimProduct), bangun "tabel hash" (seperti kamus/contekan) di memori. Lalu, baca tabel besar (FactSales) satu per satu dan "cocokkan" ke kamus di memori tadi.
  • Kapan Bagus: Ini adalah pekerja keras untuk set data besar yang tidak terurut. Sangat umum di data warehouse.

Grup 5: Konsep Lanjutan

14. Columnstore Index (Indeks Kolom)

  • Definisi Sederhana: Menyimpan data berdasarkan kolom, bukan berdasarkan baris.
  • Analogi:
    • Row-Store (biasa): Menyimpan data seperti di buku catatan:
      (Baris 1: Faisal, Ayam KUB, 1000)
      (Baris 2: Abdau, Entok, 500)
    • Columnstore (analitik): Menyimpan data seperti ini:
      (Kolom Nama: Faisal, Abdau)
      (Kolom Bisnis: Ayam KUB, Entok)
      (Kolom Kuantitas: 1000, 500)
  • Kapan Ini Penting: Saat Anda melakukan kueri analitik seperti SUM(Kuantitas), Columnstore hanya membaca kolom (1000, 500) dan mengabaikan kolom Nama dan Bisnis. Ini luar biasa cepat untuk agregasi di tabel fakta yang besar.

15. SQL Hints (Petunjuk SQL)

  • Definisi Sederhana: "Perintah" dari Anda ke Optimizer untuk memaksanya menggunakan rencana tertentu. Contoh: OPTION (USE HASH JOIN).
  • Analogi: Anda bilang ke Google Maps: "Saya tidak peduli kata Anda macet, saya HARUS lewat jalan tol!"
  • Kapan Ini Penting: Ini adalah alat "darurat". Sangat berbahaya karena rencana yang bagus hari ini (di data kecil) bisa menjadi bencana besok (di data besar). Gunakan hanya jika Anda sangat yakin Optimizer salah.

🗣️ Cara Mengajarkan Ini ke Orang Lain (Agar Anda Makin Paham)

Inilah draf materi yang bisa Anda gunakan untuk mengajar tim Anda, junior Anda, atau bahkan hanya untuk "berbicara" pada diri sendiri. Mengajarkan adalah cara terbaik untuk belajar.

(Mulai di sini)

Hei kawan-kawan,

Hari ini kita akan bicara tentang sesuatu yang sering jadi "kotak hitam": Kenapa kueri SQL kita lambat?

Banyak dari kita, termasuk saya, sering main tebak-tebakan. "Oh, mungkin kurang indeks di kolom X," atau "Coba JOIN-nya dibalik." Kadang berhasil, kadang tidak.

Masalahnya adalah, kita menebak.

Bagaimana kalau kita bisa berhenti menebak dan mulai mendiagnosis? Bagaimana kalau kita bisa melihat apa yang sebenarnya database pikirkan?

"Google Maps" untuk Kueri Anda

Itulah yang disebut Execution Plan (Rencana Eksekusi).

Anggap saja kueri SELECT Anda adalah permintaan "Tolong carikan saya rute dari Purworejo ke Yogyakarta."

Database tidak langsung jalan. Ia akan membuka "Google Maps"-nya (namanya Query Optimizer) dan membuat rencana rute terbaik. Rute inilah yang akan kita "baca".

Di SSMS, Anda cukup menekan Ctrl+M (Include Actual Execution Plan) sebelum menjalankan kueri Anda.

Cara Membaca Rute: Dari Kanan ke Kiri

Setelah kueri selesai, akan muncul tab "Execution Plan". Aturannya aneh: Anda harus membacanya dari kanan ke kiri.

  • Operator paling kanan adalah hal pertama yang database lakukan (biasanya mengambil data dari tabel).
  • Operator paling kiri adalah hasil akhirnya (data yang Anda lihat).

Tiga Ikon yang Wajib Anda Hafal

Saat Anda melihat rute itu, Anda hanya perlu fokus pada tiga hal ini dulu. Ini adalah lampu lalu lintas performa Anda:

1. 🟢 Index Seek (Bagus!)

  • Artinya: Database tahu persis di mana data Anda berada dan langsung melompat ke sana.
  • Analogi: Menggunakan indeks di belakang buku. Cepat dan efisien.
  • Target kita: Selalu usahakan WHERE dan JOIN Anda menghasilkan Index Seek.

2. 🔴 Table Scan (Buruk!)

  • Artinya: Database terpaksa membaca seluruh isi tabel dari baris pertama sampai terakhir.
  • Analogi: Mencari satu kata di novel tanpa indeks, jadi Anda harus membaca setiap halaman.
  • Tindakan: Jika Anda melihat ini di tabel besar, ini adalah biang kerok #1 kueri lambat Anda. Solusinya? Tambahkan Non-Clustered Index pada kolom yang Anda WHERE.

3. 🟡 Key Lookup (Perangkap!)

  • Artinya: Ini adalah operasi "kerja dua kali" yang licik.
  • Analogi: Anda mencari topik di indeks buku (Index Seek), menemukan di halaman 50. Tapi Anda juga butuh gambar yang terkait, yang ada di lampiran belakang. Jadi Anda harus pergi lagi ke lampiran (Key Lookup).
  • Penyebabnya: Ini hampir selalu disebabkan oleh SELECT *. Anda Seek pakai indeks, tapi karena Anda minta semua kolom, database terpaksa kembali ke tabel utama untuk mengambil kolom yang tidak ada di indeks.
  • Solusi:
    1. Jangan SELECT *! Hanya SELECT kolom yang Anda butuhkan.
    2. Jika Anda memang butuh kolom ekstra itu, tambahkan ke indeks Anda menggunakan INCLUDE.

Aksi Nyata Hari Ini

Saya ingin Anda melakukan satu hal:

  1. Ambil satu kueri lambat yang sering Anda pakai.
  2. Tekan Ctrl+M di SSMS.
  3. Jalankan kuerinya.
  4. Lihat tab "Execution Plan". Baca dari kanan ke kiri.
  5. Cari satu Table Scan atau Index Scan yang paling mahal (arahkan kursor untuk melihat Estimated Cost).
  6. Tanyakan pada diri Anda: "Kolom apa yang difilter di operator ini? Apakah sudah ada indeks di sana?"

Dengan melakukan ini, Anda sudah beralih dari "penebak" menjadi "detektif performa".

(Selesai)

Contoh Mengerjakan Project Data Analyst 1 - DATA ANALYSIS INDONESIA