sql >> Databáze >  >> RDS >> Sqlserver

Je SQL Server DRI (ON DELETE CASCADE) pomalý?

SQL Server je nejlepší v operacích založených na množinách, zatímco CASCADE mazání jsou ze své podstaty založeny na záznamech.

SQL Server , na rozdíl od ostatních serverů, se snaží optimalizovat okamžité operace založené na množinách, ale funguje to jen o jednu úroveň. Aby bylo možné odstranit záznamy v tabulkách nižší úrovně, musí být odstraněny záznamy v tabulkách vyšší úrovně.

Jinými slovy, kaskádové operace fungují nahoru-dolů, zatímco vaše řešení funguje dolů-nahoru, což je více založené na nastavení a efektivnější.

Zde je ukázkové schéma:

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)

, tento dotaz:

DELETE
FROM    t_g
WHERE   id > 50000

a jeho plán:

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

Nejprve SQL Server odstraní záznamy z t_g , pak smazané záznamy spojí pomocí t_p a odstraní z posledně jmenovaného, ​​nakonec spojí záznamy odstraněné z t_p s t_c a odstraní z t_c .

Jediné spojení tří stolů by v tomto případě bylo mnohem efektivnější, a to je to, co uděláte s vaším řešením.

Pokud se díky tomu cítíte lépe, Oracle nijak neoptimalizuje kaskádové operace:vždy se jedná o NESTED LOOPS a Bůh vám pomáhej, pokud jste zapomněli vytvořit index ve sloupci s odkazy.




  1. Pro Matlab a MySQL nebyl nalezen žádný vhodný ovladač

  2. Příkaz PHP SQL Foreach

  3. Typ přetypování řetězce na celé číslo

  4. WEEKDAY() vs DAYOFWEEK() v MariaDB:Jaký je rozdíl?