SQL Server
paling baik dalam operasi berbasis himpunan, sedangkan CASCADE
penghapusan, pada dasarnya, berbasis catatan.
SQL Server
, tidak seperti server lain, mencoba untuk mengoptimalkan operasi berbasis set langsung, namun, ia bekerja hanya dalam satu tingkat. Catatan harus dihapus di tabel tingkat atas untuk menghapus catatan di tabel tingkat bawah.
Dengan kata lain, operasi cascading bekerja dari atas ke bawah, sementara solusi Anda bekerja dari bawah ke atas, yang lebih berbasis set dan efisien.
Berikut contoh skemanya:
CREATE TABLE t_g (id INT NOT NULL PRIMARY KEY)
CREATE TABLE t_p (id INT NOT NULL PRIMARY KEY, g INT NOT NULL, CONSTRAINT fk_p_g FOREIGN KEY (g) REFERENCES t_g ON DELETE CASCADE)
CREATE TABLE t_c (id INT NOT NULL PRIMARY KEY, p INT NOT NULL, CONSTRAINT fk_c_p FOREIGN KEY (p) REFERENCES t_p ON DELETE CASCADE)
CREATE INDEX ix_p_g ON t_p (g)
CREATE INDEX ix_c_p ON t_c (p)
, kueri ini:
DELETE
FROM t_g
WHERE id > 50000
dan rencananya:
|--Sequence
|--Table Spool
| |--Clustered Index Delete(OBJECT:([test].[dbo].[t_g].[PK__t_g__176E4C6B]), WHERE:([test].[dbo].[t_g].[id] > (50000)))
|--Index Delete(OBJECT:([test].[dbo].[t_p].[ix_p_g]) WITH ORDERED PREFETCH)
| |--Sort(ORDER BY:([test].[dbo].[t_p].[g] ASC, [test].[dbo].[t_p].[id] ASC))
| |--Table Spool
| |--Clustered Index Delete(OBJECT:([test].[dbo].[t_p].[PK__t_p__195694DD]) WITH ORDERED PREFETCH)
| |--Sort(ORDER BY:([test].[dbo].[t_p].[id] ASC))
| |--Merge Join(Inner Join, MERGE:([test].[dbo].[t_g].[id])=([test].[dbo].[t_p].[g]), RESIDUAL:([test].[dbo].[t_p].[g]=[test].[dbo].[t_g].[id]))
| |--Table Spool
| |--Index Scan(OBJECT:([test].[dbo].[t_p].[ix_p_g]), ORDERED FORWARD)
|--Index Delete(OBJECT:([test].[dbo].[t_c].[ix_c_p]) WITH ORDERED PREFETCH)
|--Sort(ORDER BY:([test].[dbo].[t_c].[p] ASC, [test].[dbo].[t_c].[id] ASC))
|--Clustered Index Delete(OBJECT:([test].[dbo].[t_c].[PK__t_c__1C330188]) WITH ORDERED PREFETCH)
|--Table Spool
|--Sort(ORDER BY:([test].[dbo].[t_c].[id] ASC))
|--Hash Match(Inner Join, HASH:([test].[dbo].[t_p].[id])=([test].[dbo].[t_c].[p]))
|--Table Spool
|--Index Scan(OBJECT:([test].[dbo].[t_c].[ix_c_p]), ORDERED FORWARD)
Pertama, SQL Server
menghapus catatan dari t_g
, lalu gabungkan catatan yang dihapus dengan t_p
dan menghapus dari yang terakhir, akhirnya, menggabungkan catatan yang dihapus dari t_p
dengan t_c
dan menghapus dari t_c
.
Penggabungan tiga tabel tunggal akan jauh lebih efisien dalam kasus ini, dan inilah yang Anda lakukan dengan solusi Anda.
Jika itu membuat Anda merasa lebih baik, Oracle
tidak mengoptimalkan operasi kaskade dengan cara apa pun:operasi tersebut selalu NESTED LOOPS
dan Tuhan membantu Anda jika Anda lupa membuat indeks pada kolom referensi.