Menghindari Perulangan Tak Terbatas
Batas kedalaman dan deteksi siklus.
Menghindari Perulangan Tak Terbatas adalah pelajaran SQL Academy gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar SQL Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus SQL Academy mencakup 4 pelajaran total.
Masalah Perulangan Tak Terbatas
CTE rekursif memang ampuh, tetapi juga memiliki risiko serius: jika kueri Anda tidak pernah mencapai kasus dasar, kueri tersebut akan berulang selamanya, menghabiskan seluruh memori yang tersedia, dan menyebabkan sesi basis data berhenti.
Memahami penyebab perulangan tak terbatas adalah langkah pertama untuk mencegahnya.
Kapan Perulangan Tidak Pernah Berakhir?
CTE rekursif berulang tanpa henti ketika bagian rekursif terus menghasilkan baris baru tanpa pernah mencapai keadaan ketika tidak ada baris baru yang dihasilkan.
Hal ini biasanya terjadi dalam dua keadaan: kondisi penghentian yang hilang atau salah, atau data bersiklus ketika simpul A menunjuk ke B dan B menunjuk kembali ke A.
-- Simple recursive CTE that WOULD loop forever
-- (do NOT run this as-is; illustration only)
WITH RECURSIVE counter AS (
SELECT 1 AS n -- base case
UNION ALL
SELECT n + 1 -- recursive term
FROM counter
-- no WHERE clause to stop it!
)
SELECT n FROM counter;Menambahkan Batas Kedalaman
Perlindungan paling sederhana adalah penghitung kedalaman. Tambahkan kolom yang bertambah 1 pada setiap langkah rekursif, lalu berhenti ketika nilainya melampaui kedalaman maksimum.
Cara ini menjamin penghentian, apa pun datanya, dan batas yang dipilih memberikan batas pengaman.
WITH RECURSIVE counter AS (
SELECT 1 AS n
UNION ALL
SELECT n + 1
FROM counter
WHERE n < 10 -- stop at depth 10
)
SELECT n FROM counter;Batas Kedalaman dalam Kueri Hierarki
Saat menelusuri hierarki karyawan, Anda dapat melacak kedalaman bersama jalur. Klausa WHERE depth < 5 mencegah penelusuran melampaui 5 tingkat, meskipun data memiliki tautan yang lebih dalam atau melingkar.
CREATE TEMP TABLE employees (
id INT PRIMARY KEY,
name TEXT,
manager_id INT
);
INSERT INTO employees VALUES
(1, 'Alice', NULL),
(2, 'Bob', 1),
(3, 'Carol', 2),
(4, 'Dave', 3);
WITH RECURSIVE hierarchy AS (
SELECT id, name, manager_id, 1 AS depth
FROM employees
WHERE manager_id IS NULL -- root
UNION ALL
SELECT e.id, e.name, e.manager_id, h.depth + 1
FROM employees e
JOIN hierarchy h ON e.manager_id = h.id
WHERE h.depth < 5 -- depth limit
)
SELECT id, name, depth FROM hierarchy ORDER BY depth, id;Apa Itu Deteksi Siklus?
Siklus terjadi dalam data graf ketika mengikuti sisi-sisi tertentu pada akhirnya membawa Anda kembali ke simpul yang sudah dikunjungi. Contohnya: A → B → C → A.
Batas kedalaman tetap menghentikan kueri pada data bersiklus, tetapi tidak memberi tahu Anda di mana siklus tersebut berada. Deteksi siklus secara eksplisit dapat memberitahukannya.
CREATE TEMP TABLE edges (
from_node INT,
to_node INT
);
-- Introduce a cycle: 1->2->3->1
INSERT INTO edges VALUES
(1, 2),
(2, 3),
(3, 1), -- cycle back to 1
(1, 4); -- also a non-cyclic branch
SELECT * FROM edges;Melacak Simpul yang Telah Dikunjungi dengan Larik
Teknik deteksi siklus yang kuat adalah membawa larik berisi ID simpul yang telah dikunjungi selama rekursi. Sebelum mengunjungi simpul berikutnya, periksa apakah simpul tersebut sudah ada di dalam larik. Jika sudah, lewati simpul itu.
PostgreSQL mempermudah hal ini dengan operator ANY(array) dan operator penambahan larik ||.
WITH RECURSIVE traverse AS (
-- Start from node 1
SELECT from_node,
to_node,
ARRAY[from_node] AS visited
FROM edges
WHERE from_node = 1
UNION ALL
SELECT e.from_node,
e.to_node,
t.visited || e.from_node
FROM edges e
JOIN traverse t ON e.from_node = t.to_node
WHERE NOT (e.from_node = ANY(t.visited)) -- skip visited nodes
)
SELECT from_node, to_node, visited
FROM traverse;Klausa CYCLE (PostgreSQL 14+)
PostgreSQL 14 memperkenalkan klausa bawaan CYCLE untuk CTE rekursif. Klausa ini secara otomatis menambahkan dua kolom: penanda boolean yang bernilai true ketika siklus terdeteksi, dan larik yang mencatat jalur yang ditempuh.
Cara ini lebih rapi daripada mengelola larik secara manual.
WITH RECURSIVE traverse AS (
SELECT from_node, to_node
FROM edges
WHERE from_node = 1
UNION ALL
SELECT e.from_node, e.to_node
FROM edges e
JOIN traverse t ON e.from_node = t.to_node
)
CYCLE from_node SET is_cycle USING path
SELECT from_node, to_node, is_cycle, path
FROM traverse;Menggabungkan Batas Kedalaman dan Deteksi Siklus
Menggunakan batas kedalaman dan deteksi siklus secara bersamaan memberikan jaminan keamanan terkuat:
- Batas kedalaman bertindak sebagai batas mutlak, apa pun kualitas datanya.
- Deteksi siklus berhenti segera setelah menemukan perulangan, sehingga menghemat iterasi yang tidak diperlukan.
Dalam kueri produksi, selalu terapkan setidaknya salah satu perlindungan ini.
WITH RECURSIVE traverse AS (
SELECT from_node,
to_node,
1 AS depth,
ARRAY[from_node] AS visited
FROM edges
WHERE from_node = 1
UNION ALL
SELECT e.from_node,
e.to_node,
t.depth + 1,
t.visited || e.from_node
FROM edges e
JOIN traverse t ON e.from_node = t.to_node
WHERE t.depth < 10 -- depth limit
AND NOT (e.from_node = ANY(t.visited)) -- cycle guard
)
SELECT from_node, to_node, depth, visited
FROM traverse;Membangun Jalur Lengkap sebagai Teks
Bersamaan dengan deteksi siklus, mencatat seluruh jalur penelusuran sebagai teks yang mudah dibaca manusia juga berguna. Menggabungkan ID simpul dengan pemisah -> memudahkan Anda menampilkan atau men-debug rute yang dilalui dalam graf.
WITH RECURSIVE traverse AS (
SELECT from_node,
to_node,
1 AS depth,
ARRAY[from_node] AS visited,
from_node::TEXT AS path_str
FROM edges
WHERE from_node = 1
UNION ALL
SELECT e.from_node,
e.to_node,
t.depth + 1,
t.visited || e.from_node,
t.path_str || ' -> ' || e.from_node::TEXT
FROM edges e
JOIN traverse t ON e.from_node = t.to_node
WHERE t.depth < 10
AND NOT (e.from_node = ANY(t.visited))
)
SELECT from_node, to_node, path_str, depth
FROM traverse
ORDER BY depth;Menetapkan Batas Iterasi Rekursif Maksimum
Beberapa basis data (MariaDB, MySQL versi lama) menggunakan variabel sesi untuk membatasi rekursi. Dalam PostgreSQL, pendekatan yang setara adalah mengandalkan penghitung kedalaman yang Anda tulis sendiri atau menggunakan batas waktu pernyataan.
Menetapkan statement_timeout merupakan jaring pengaman pilihan terakhir yang menghentikan kueri yang berjalan tanpa kendali setelah waktu tertentu.
-- PostgreSQL: set a statement timeout as a safety net
SET statement_timeout = '5s';
-- Now any query that runs longer than 5 seconds is cancelled
WITH RECURSIVE counter AS (
SELECT 1 AS n
UNION ALL
SELECT n + 1 FROM counter WHERE n < 1000000
)
SELECT MAX(n) FROM counter;
-- Reset to default when done
SET statement_timeout = '0';Memilih Batas Kedalaman yang Tepat
Tidak ada batas kedalaman yang berlaku secara universal. Pilih batas berdasarkan kedalaman maksimum yang realistis dalam data Anda:
- Bagan organisasi jarang melebihi 10–15 tingkat — gunakan
depth < 20sebagai cadangan yang memadai. - Pohon sistem berkas dapat memiliki kedalaman 50–100 tingkat.
- Penelusuran graf jejaring sosial sering dibatasi hingga 3–6 lompatan.
Tetapkan batas yang cukup tinggi untuk mencakup data yang valid, tetapi cukup rendah untuk mendeteksi kueri yang berjalan tanpa kendali sejak awal.
-- Example: org chart with a generous but safe depth cap
WITH RECURSIVE org AS (
SELECT id, name, manager_id, 1 AS depth
FROM employees
WHERE manager_id IS NULL
UNION ALL
SELECT e.id, e.name, e.manager_id, o.depth + 1
FROM employees e
JOIN org o ON e.manager_id = o.id
WHERE o.depth < 20 -- realistic upper bound for an org chart
)
SELECT id, name, depth
FROM org
ORDER BY depth, name;Batas Kedalaman vs Deteksi Siklus
Teknik mana yang sebaiknya Anda gunakan?
Rangkuman: Menjaga Keamanan Kueri Rekursif
Berikut rangkuman tentang hal-hal yang Anda pelajari untuk menghindari perulangan tak terbatas dalam CTE rekursif:
- Batas kedalaman — tambahkan kolom penghitung dan berhenti dengan
WHERE depth < N. Selalu efektif dan mudah diterapkan. - Deteksi siklus berbasis larik — bawa ID simpul yang telah dikunjungi dalam sebuah larik dan lewati simpul yang sudah ada di dalamnya. Berhenti sejak siklus pertama ditemukan.
- Klausa CYCLE (PostgreSQL 14+) — sintaks bawaan yang mengotomatiskan pelacakan siklus dengan kolom
is_cycledanpath. - Batas waktu pernyataan — jaring pengaman tingkat basis data untuk kueri yang berjalan tanpa kendali, bukan pengganti logika yang tepat.
- Gabungkan keduanya — gunakan batas kedalaman dan deteksi siklus dalam produksi untuk mendapatkan jaminan terkuat.
Dengan teknik-teknik ini, Anda dapat menelusuri hierarki dan graf dengan percaya diri tanpa membahayakan basis data.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Menghindari Perulangan Tak Terbatas” gratis?
Ya — teks lengkap “Menghindari Perulangan Tak Terbatas” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus SQL Academy, upgrade ke CoddyKit PRO. Kursus SQL Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Menghindari Perulangan Tak Terbatas”?
Batas kedalaman dan deteksi siklus. Kamu berlatih SQL Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai SQL Academy?
Tidak diperlukan pengalaman sebelumnya. SQL Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.
Berapa lama pelajaran “Menghindari Perulangan Tak Terbatas” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran SQL Academy ini?
Ya. Setiap pelajaran SQL Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Cara Kerja CTE Rekursif
- Menelusuri Pohon Kategori
- Membuat Deret dan Urutan
- Menghindari Perulangan Tak Terbatas