sql >> Database teknologi >  >> RDS >> Sqlserver

Er SQL Server DRI (ON DELETE CASCADE) langsom?

SQL-server er bedst til sæt-baserede operationer, mens CASCADE sletninger er i sagens natur registreringsbaserede.

SQL-server , i modsætning til de andre servere, forsøger at optimere de øjeblikkelige sæt-baserede operationer, men det virker kun et niveau dybt. Det skal have posterne slettet i tabellerne på øverste niveau for at slette dem i tabellerne på lavere niveau.

Med andre ord fungerer cascading operationer op og ned, mens din løsning arbejder ned og op, hvilket er mere set-baseret og effektivt.

Her er et eksempelskema:

OPRET TABEL t_g (id INT IKKE NULL PRIMÆR NØGLE)OPRET TABEL t_p (id INT IKKE NULL PRIMÆR NØGLE, g INT IKKE NULL, BEGRÆNSNING fk_p_g UDENLANDSKE NØGLE (g) REFERENCER t_g PÅ SLETT CASAT (g) id INT IKKE NULL PRIMÆR NØGLE, p INT IKKE NULL, BEGRÆNSNING fk_c_p UDENLANDSKE NØGLE (p) REFERENCER t_p PÅ SLET CASCADE)CREATE INDEX ix_p_g ON t_p (g)CREATE INDEX ix_c_p ON _code 

, denne forespørgsel:

DELETEFROM t_gWHERE id> 50000 

og dens plan:

|--Sekvens |--Tabelspole | |--Clustered Index Delete(OBJECT:([test].[dbo].[t_g].[PK__t_g__176E4C6B]), HVOR:([test].[dbo].[t_g].[id]> (50000)) ) |--Index Delete(OBJECT:([test].[dbo].[t_p].[ix_p_g]) MED BESTILLET FORFETCH) | |--Sort(ORDER BY:([test].[dbo].[t_p].[g] ASC, [test].[dbo].[t_p].[id] ASC)) | |--Bordspole | |--Clustered Index Delete(OBJECT:([test].[dbo].[t_p].[PK__t_p__195694DD]) MED BESTILLET FORFØTNING) | |--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])) | |--Bordspole | |--Index Scan(OBJECT:([test].[dbo].[t_p].[ix_p_g]), BESTILLET FREM) |--Index Delete(OBJECT:([test].[dbo].[t_c]. [ix_c_p]) MED BESTILLET FORFETCH) |--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]) MED BESTILLET FORFETCH) |--Tabelspole |--Sort(ORDER BY:([test]. [dbo].[t_c].[id] ASC)) |--Hash Match(Indre Join, HASH:([test].[dbo].[t_p].[id])=([test].[dbo] ].[t_c].[p])) |--Tabelspole |--Index Scan(OBJECT:([test].[dbo].[t_c].[ix_c_p]), BESTILLET VIDERE)

Først SQL-server sletter poster fra t_g , og forbinder derefter de slettede poster med t_p og sletter fra sidstnævnte, slutter sig til poster slettet fra t_p med t_c og sletter fra t_c .

En enkelt tre-bords joinforbindelse ville være meget mere effektiv i dette tilfælde, og det er, hvad du gør med din løsning.

Hvis det får dig til at føle dig bedre, Oracle optimerer ikke kaskadeoperationer på nogen måde:de er altid NESTED LOOPS og Gud hjælpe dig, hvis du har glemt at oprette et indeks i referencekolonnen.




  1. Bedste måde at udvikle/administrere/designe tilbagevendende opgaver/kalender

  2. Threading og SqlFileStream. Processen kan ikke få adgang til den angivne fil, fordi den er blevet åbnet i en anden transaktion

  3. Eksekverer MySQL SELECT *-forespørgsel parallelt

  4. Oracle:tabellen muterer