SQL Server
CASCADE
はセットベースの操作に最適です。 削除は、その性質上、レコードベースです。
SQL Server
は、他のサーバーとは異なり、即時のセットベースの操作を最適化しようとしますが、1 レベルの深さでしか機能しません。下位テーブルのレコードを削除するには、上位テーブルのレコードを削除する必要があります。
言い換えると、カスケード操作は上から下に動作しますが、ソリューションは下から上に動作します。これは、よりセットベースで効率的です。
サンプル スキーマは次のとおりです。
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)
、このクエリ:
DELETE
FROM t_g
WHERE id > 50000
とその計画:
|--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)
まず、SQL Server
t_g
からレコードを削除します 、次に t_p
で削除されたレコードを結合します 後者から削除し、最後に t_p
から削除されたレコードを結合します t_c
で t_c
から削除します .
この場合、1 つの 3 つのテーブルを結合する方がはるかに効率的であり、これが回避策で行うことです。
気分が良くなったら Oracle
カスケード操作は決して最適化されません:それらは常に NESTED LOOPS
です 参照列にインデックスを作成するのを忘れた場合は、神が助けてくれます。