Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Apakah SQL Server DRI (ON DELETE CASCADE) lambat?

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.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. EF5:Tidak dapat melampirkan file '{0}' sebagai database '{1}'

  2. ATAU Operator korsleting di SQL Server

  3. 3 Cara Mengekstrak Bulan dari Tanggal di SQL Server (T-SQL)

  4. saya ingin mendapatkan semua kolom tabel Akun dengan kueri ini tetapi memberikan kesalahan

  5. Bagaimana cara menerapkan LIMIT dengan SQL Server?