Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Czy SQL Server DRI (ON DELETE CASCADE) jest wolny?

SQL Server najlepiej sprawdza się w operacjach opartych na zbiorach, podczas gdy CASCADE usunięcia są ze swej natury oparte na zapisach.

SQL Server , w przeciwieństwie do innych serwerów, próbuje zoptymalizować natychmiastowe operacje oparte na zbiorach, jednak działa tylko na jednym poziomie. Musi usunąć rekordy z tabel wyższego poziomu, aby usunąć te z tabel niższego poziomu.

Innymi słowy, operacje kaskadowe działają w górę, podczas gdy rozwiązanie działa w dół, co jest bardziej oparte na zestawie i wydajne.

Oto przykładowy schemat:

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)

, to zapytanie:

DELETE
FROM    t_g
WHERE   id > 50000

i jego plan:

  |--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)

Najpierw SQL Server usuwa rekordy z t_g , a następnie łączy usunięte rekordy za pomocą t_p i usuwa z tego ostatniego, w końcu łączy rekordy usunięte z t_p z t_c i usuwa z t_c .

W tym przypadku pojedyncze złączenie trzech tabel byłoby znacznie bardziej wydajne i właśnie to robisz ze swoim obejściem.

Jeśli dzięki temu poczujesz się lepiej, Oracle nie optymalizuje w żaden sposób operacji kaskadowych:zawsze są to NESTED LOOPS i Boże pomóż ci, jeśli zapomniałeś utworzyć indeks w kolumnie referencyjnej.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sposoby migracji bazy danych SQL Server do Azure SQL Database

  2. Zapytanie SQL dla przedziałów czasowych. Błędy składni.

  3. Jak usunąć ograniczenia klucza obcego w bazie danych SQL Server dla wszystkich tabel — samouczek SQL Server / TSQL, część 72

  4. Pobierz listę obliczonych kolumn w tabeli bazy danych (SQL Server)

  5. Jak mapować wiele partycji do jednej grupy plików w programie SQL Server (T-SQL)