sql >> Databasteknik >  >> RDS >> Sqlserver

Är SQL Server DRI (ON DELETE CASCADE) långsam?

SQL Server är bäst på set-baserade operationer, medan CASCADE raderingar är till sin natur postbaserade.

SQL Server , till skillnad från de andra servrarna, försöker optimera de omedelbara set-baserade operationerna, men det fungerar bara en nivå djupt. Den måste ha posterna raderade i tabellerna på den övre nivån för att radera dem i tabellerna på lägre nivå.

Med andra ord, kaskadoperationer fungerar upp och ner, medan din lösning fungerar ner och upp, vilket är mer set-baserat och effektivt.

Här är ett exempelschema:

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)

, denna fråga:

DELETE
FROM    t_g
WHERE   id > 50000

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

Först, SQL Server tar bort poster från t_g , ansluter sedan de raderade poster med t_p och raderar från den senare, slutligen, sammanfogar poster raderade från t_p med t_c och raderar från t_c .

En enstaka koppling med tre tabeller skulle vara mycket effektivare i det här fallet, och det är vad du gör med din lösning.

Om det får dig att må bättre, Oracle optimerar inte kaskadoperationer på något sätt:de är alltid NESTED LOOPS och Gud hjälpa dig om du glömde att skapa ett index i referenskolumnen.




  1. SSRS-rapportdefinitionen är nyare än Server

  2. Laravel:ordning efter var i

  3. MySQL - InnoDB vs MyISAM

  4. Vad betyder hakparenteser i Oracle SQL-fråga?